Bug 319818

Summary: [WebTransport] Flow control never refills
Product: WebKit Reporter: kixelated
Component: Page LoadingAssignee: Nobody <webkit-unassigned>
Status: NEW    
Severity: Normal CC: achristensen, ankshit_jain, beidson, elijahdisch, floatdrop, rgovostes+wk, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: Safari 26   
Hardware: Mac (Apple Silicon)   
OS: macOS 26   
Attachments:
Description Flags
repro example none

kixelated
Reported 2026-07-20 09:41:55 PDT
I'm using WebTransport for MoQ: https://moq.dev/watch/ After a short period of time, the WebTransport connection on Safari will deadlock because it hits flow control limits. I've reproduced the issue, it happens when Safari receives 16MB (MAX_DATA) or 7600 streams (MAX_STREAMS), whichever happens first. It seems like Safari never frees up flow control even when streams are FIN or RESET. This is not using WebTransport flow control; just QUIC flow control.
Attachments
repro example (5.04 KB, application/octet-stream)
2026-08-19 11:24 PDT, Ryan Govostes
no flags
Radar WebKit Bug Importer
Comment 1 2026-07-20 18:52:46 PDT
Ryan Govostes
Comment 2 2026-08-19 11:24:35 PDT
Created attachment 481114 [details] repro example I hit the same issue, also while trying to render a MoQ video stream. I'm attaching a minimal repro case (~150 lines backend, ~100 lines frontend), generated by Claude Fable 5.
elijahdisch
Comment 3 2026-08-26 04:32:35 PDT
Reproducible on Firefox 154 on iOS 26.6.1, presumably due to embedded WKWebView.
floatdrop
Comment 4 2026-10-18 20:46:32 PDT
We reproduce this with a different MoQ server, so it doesn't look specific to moq.dev's relay: ours is moq-go (Go, on quic-go with webtransport-go, MoQT draft-22), and the page uses WebTransport directly. Setup: the relay opens one unidirectional stream per MoQ group towards the browser (at the time, one per 20 ms audio frame, about 50 streams/s). The page reads every stream to its FIN. Safari 27 on macOS 26.7.1 (25G241): - A session stops receiving after 98 server-initiated unidirectional streams. Safari never sends further MAX_STREAMS (uni) for that session, although the page has read every one of those streams to its FIN. From then on the relay's qlog shows it blocked on stream credit (STREAMS_BLOCKED). - In a qlog of an earlier call, Safari did send some MAX_STREAMS updates, but they covered only about half of the streams the page had finished. It never sent MAX_DATA beyond the initial 16 MiB, so the connection also runs out of data credit after 16 MiB. - QUIC DATAGRAMs keep arriving after the stall (24,970 of 24,970, 23.8 MiB), as expected since they aren't flow-controlled. - A new WebTransport session opened after the stall receives normally. Each session got a QUIC connection (and client port) of its own, starting with fresh credit. Chrome and Yandex Browser against the same relay return stream and data credit as streams finish, and never stall. Our workaround for WebKit: audio is sent as datagrams, and video is received on dedicated WebTransport sessions that are replaced every 60 s, or after 80 streams or 12 MiB, before they run out of credit.
Note You need to log in before you can comment on or make changes to this bug.