{"record":{"id":"9c03483d5b866a12","repo":"cloudflare/cloudflared","slug":"unknown-protocol-v-9c0348","errorCode":null,"errorMessage":"unknown protocol %v","messagePattern":"unknown protocol (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tunnelrpc/quic/session_server.go","lineNumber":37,"sourceCode":"func NewSessionManagerServer(sessionManager pogs.SessionManager, responseTimeout time.Duration) *SessionManagerServer {\n\treturn &SessionManagerServer{\n\t\tsessionManager:  sessionManager,\n\t\tresponseTimeout: responseTimeout,\n\t}\n}\n\nfunc (s *SessionManagerServer) Serve(ctx context.Context, stream io.ReadWriteCloser) error {\n\tsignature, err := determineProtocol(stream)\n\tif err != nil {\n\t\treturn err\n\t}\n\tswitch signature {\n\tcase rpcStreamProtocolSignature:\n\t\tbreak\n\tcase dataStreamProtocolSignature:\n\t\treturn errDataStreamNotSupported\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown protocol %v\", signature)\n\t}\n\n\t// Every new quic.Stream request aligns to a new RPC request, this is why there is a timeout for the server-side\n\t// of the RPC request.\n\tctx, cancel := context.WithTimeout(ctx, s.responseTimeout)\n\tdefer cancel()\n\n\ttransport := tunnelrpc.SafeTransport(stream)\n\tdefer transport.Close()\n\n\tmain := pogs.SessionManager_ServerToClient(s.sessionManager)\n\trpcConn := tunnelrpc.NewServerConn(transport, main.Client)\n\tdefer rpcConn.Close()\n\n\tselect {\n\tcase <-rpcConn.Done():\n\t\treturn nil\n\tcase <-ctx.Done():","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/tunnelrpc/quic/session_server.go#L19-L55","documentation":"The RPC session server (Serve) reads the stream's 6-byte protocol signature and only accepts the RPC stream signature; a data-stream signature yields errDataStreamNotSupported and anything else yields this error. It means the server received a stream preamble it does not recognize as a supported protocol.","triggerScenarios":"A peer writes neither rpcStreamProtocolSignature nor dataStreamProtocolSignature as its first 6 bytes before the server calls Serve — e.g. a different cloudflared version, a hand-rolled client, or garbage bytes on the stream.","commonSituations":"Version skew between client and server where the signature scheme changed; a client sending payload data directly without the preamble; corruption of the first bytes on the stream.","solutions":["Ensure the client writes rpcStreamProtocolSignature as the first 6 bytes when opening an RPC stream","Align client and server cloudflared versions","Inspect the %v value in the message to see the actual bytes received","If the client intended a data stream, use the corresponding data-stream serving path instead"],"exampleFix":"// before: client writes data preamble to an RPC-serving stream\nwriteDataStreamPreamble(stream)\n// after: write the RPC signature the server expects\nif err := writeSignature(stream, rpcStreamProtocolSignature); err != nil {\n    return err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := server.Serve(ctx, stream)\nif err != nil {\n    if strings.Contains(err.Error(), \"unknown protocol\") {\n        // close stream; peer sent an unrecognized preamble\n        stream.Close()\n        return errUnsupportedPeerProtocol\n    }\n    return err\n}","preventionTips":["Ensure clients write the RPC signature before any data on RPC streams","Log the received signature bytes to diagnose version skew early","Upgrade/downgrade peers so both sides speak the same signature scheme"],"tags":["quic","rpc","protocol-handshake"],"backgroundTag":"invalid-argument-value","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"}