{"record":{"id":"f1293f06b92b8aed","repo":"cloudflare/cloudflared","slug":"data-protocol-not-supported","errorCode":null,"errorMessage":"data protocol not supported","messagePattern":"data protocol not supported","errorType":"error_code","errorClass":"errDataStreamNotSupported","httpStatus":null,"severity":"warning","filePath":"tunnelrpc/quic/protocol.go","lineNumber":19,"sourceCode":"package quic\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\n// protocolSignature defines the first 6 bytes of the stream, which is used to distinguish the type of stream. It\n// ensures whoever performs a handshake does not write data before writing the metadata.\ntype protocolSignature [6]byte\n\nvar (\n\t// dataStreamProtocolSignature is a custom protocol signature for data stream\n\tdataStreamProtocolSignature = protocolSignature{0x0A, 0x36, 0xCD, 0x12, 0xA1, 0x3E}\n\n\t// rpcStreamProtocolSignature is a custom protocol signature for RPC stream\n\trpcStreamProtocolSignature = protocolSignature{0x52, 0xBB, 0x82, 0x5C, 0xDB, 0x65}\n\n\terrDataStreamNotSupported = fmt.Errorf(\"data protocol not supported\")\n\terrRPCStreamNotSupported  = fmt.Errorf(\"rpc protocol not supported\")\n)\n\ntype protocolVersion string\n\nconst (\n\tprotocolV1 protocolVersion = \"01\"\n\n\tprotocolVersionLength = 2\n)\n\n// determineProtocol reads the first 6 bytes from the stream to determine which protocol is spoken by the client.\n// The protocols are magic byte arrays understood by both sides of the stream.\nfunc determineProtocol(stream io.Reader) (protocolSignature, error) {\n\tsignature, err := readSignature(stream)\n\tif err != nil {\n\t\treturn protocolSignature{}, err\n\t}","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/tunnelrpc/quic/protocol.go#L1-L37","documentation":"The QUIC session server only serves RPC streams; when an incoming stream presents the data-stream protocol signature it immediately returns errDataStreamNotSupported. This is a deliberate, sentinel refusal: data streams are handled by a different server (the request server), not the session RPC server.","triggerScenarios":"A QUIC stream with dataStreamProtocolSignature (0x0A36CD12A13E) reaches the session server's Serve dispatch (session_server.go), which only accepts rpcStreamProtocolSignature.","commonSituations":"Client demultiplexing bug sending a data stream to the session server; version skew where the client expects data streams on this server; misrouted stream after reconnect.","solutions":["Update cloudflared on both ends so stream demultiplexing matches.","Ensure data streams are sent to the request/stream server, not the session server.","Reconnect; if persistent, report a version-mismatch between client and edge."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"func isDataStreamSig(s protocolSignature) bool { return s == dataStreamProtocolSignature }","tryCatchPattern":"if err := sessionServer.Serve(ctx, stream); errors.Is(err, errDataStreamNotSupported) {\n    // reroute stream to the request/stream server\n    return requestServer.Serve(ctx, stream)\n}","preventionTips":["Route data streams to the request server, RPC streams to the session server","Keep demultiplexing logic in sync with protocol.go signatures","Update both ends of a tunnel together"],"tags":["protocol","quic","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}