{"record":{"id":"9c84fd4979828eac","repo":"cloudflare/cloudflared","slug":"failed-to-accept-quic-stream-w","errorCode":null,"errorMessage":"failed to accept QUIC stream: %w","messagePattern":"failed to accept QUIC stream: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"connection/quic_connection.go","lineNumber":163,"sourceCode":"// serveControlStream will serve the RPC; blocking until the control plane is done.\nfunc (q *quicConnection) serveControlStream(ctx context.Context, controlStream *quic.Stream) error {\n\treturn q.controlStreamHandler.ServeControlStream(ctx, controlStream, q.connOptions.ConnectionOptions(), q.orchestrator)\n}\n\n// Close the connection with no errors specified.\nfunc (q *quicConnection) Close() {\n\t_ = q.conn.CloseWithError(0, \"\")\n}\n\nfunc (q *quicConnection) acceptStream(ctx context.Context) error {\n\tfor {\n\t\tquicStream, err := q.conn.AcceptStream(ctx)\n\t\tif err != nil {\n\t\t\t// context.Canceled is usually a user ctrl+c. We don't want to log an error here as it's intentional.\n\t\t\tif errors.Is(err, context.Canceled) || q.controlStreamHandler.IsStopped() {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"failed to accept QUIC stream: %w\", err)\n\t\t}\n\t\tgo q.runStream(quicStream)\n\t}\n}\n\nfunc (q *quicConnection) runStream(quicStream *quic.Stream) {\n\tctx := quicStream.Context()\n\tstream := cfdquic.NewSafeStreamCloser(quicStream, q.streamWriteTimeout, q.logger)\n\tdefer func() { _ = stream.Close() }()\n\n\t// we are going to fuse readers/writers from stream <- cloudflared -> origin, and we want to guarantee that\n\t// code executed in the code path of handleStream don't trigger an earlier close to the downstream write stream.\n\t// So, we wrap the stream with a no-op write closer and only this method can actually close write side of the stream.\n\t// A call to close will simulate a close to the read-side, which will fail subsequent reads.\n\tnoCloseStream := &nopCloserReadWriter{ReadWriteCloser: stream}\n\tss := rpcquic.NewCloudflaredServer(q.handleDataStream, q.datagramHandler, q, q.rpcTimeout)\n\tif err := ss.Serve(ctx, noCloseStream); err != nil {\n\t\tq.logger.Debug().Err(err).Msg(\"Failed to handle QUIC stream\")","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/connection/quic_connection.go#L145-L181","documentation":"acceptStream loops calling q.conn.AcceptStream(ctx) to receive streams the edge opens. If AcceptStream errors for any reason other than an intentional context cancellation or a stopped control stream, the error is wrapped as `failed to accept QUIC stream` and returned, ending the Serve errgroup and triggering reconnection.","triggerScenarios":"AcceptStream returns a transport error: the QUIC connection was closed/reset by the edge, idle timeout expired, network dropped, or a QUIC protocol violation — while ctx is still live and the control stream hasn't been stopped.","commonSituations":"Long-lived idle tunnels killed by NAT/firewall UDP timeouts, edge-side connection resets during deployments, mobile/network switching, or abrupt tunnel termination from the Cloudflare dashboard.","solutions":["This is expected on reconnect cycles — verify the supervisor re-establishes the tunnel; otherwise restart cloudflared","Check firewall/NAT settings for UDP 443 idle timeouts; keep QUIC sessions alive or use --protocol http2 over TCP","Check network stability between the host and the nearest Cloudflare edge","Upgrade cloudflared if errors recur immediately after handshake"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to accept QUIC stream\") {\n    // supervisor should reconnect; log and rely on backoff\n    log.Warn().Err(err).Msg(\"QUIC stream accept failed; reconnecting\")\n}","preventionTips":["Prevent NAT/firewall from idle-expiring long-lived UDP sessions","Monitor tunnel connectivity and alert on frequent accept failures","Prefer --protocol http2 on unstable networks","Restart cloudflared after network changes if reconnection stalls"],"tags":["quic","network","stream","timeout"],"backgroundTag":"connection-refused","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}