{"record":{"id":"a8db40e7c2c85899","repo":"cloudflare/cloudflared","slug":"unknown-signature-v","errorCode":null,"errorMessage":"unknown signature %v","messagePattern":"unknown signature (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tunnelrpc/quic/protocol.go","lineNumber":44,"sourceCode":"\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}\n\tswitch signature {\n\tcase dataStreamProtocolSignature:\n\t\treturn dataStreamProtocolSignature, nil\n\tcase rpcStreamProtocolSignature:\n\t\treturn rpcStreamProtocolSignature, nil\n\tdefault:\n\t\treturn protocolSignature{}, fmt.Errorf(\"unknown signature %v\", signature)\n\t}\n}\n\nfunc writeDataStreamPreamble(stream io.Writer) error {\n\tif err := writeSignature(stream, dataStreamProtocolSignature); err != nil {\n\t\treturn err\n\t}\n\n\treturn writeVersion(stream)\n}\n\nfunc writeVersion(stream io.Writer) error {\n\t_, err := stream.Write([]byte(protocolV1)[:protocolVersionLength])\n\treturn err\n}\n\nfunc readVersion(stream io.Reader) (string, error) {\n\tversion := make([]byte, protocolVersionLength)","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/tunnelrpc/quic/protocol.go#L26-L62","documentation":"determineProtocol reads the first 6 bytes (magic signature) from a QUIC stream to identify whether the stream carries the data protocol or the RPC protocol. This error is thrown when the byte sequence read from the stream matches neither known signature, meaning the peer wrote an unrecognized preamble or no preamble at all.","triggerScenarios":"Calling ReadConnectResponseData (or any code path invoking determineProtocol) on a stream whose peer did not write one of the two 6-byte magic signatures (0x0A36CD12A13E for data, 0x52BB825CDB65 for RPC) as the first bytes; version mismatch between client and server writing different preambles; garbage or empty stream data.","commonSituations":"A cloudflared client of a different version connecting to a server expecting this handshake protocol; a stream opened by a non-cloudflared peer; corrupted or truncated QUIC stream data where the first 6 bytes are not the signature; middleware or proxies that consumed/modified the first bytes.","solutions":["Ensure both ends run compatible cloudflared versions that write the protocol signature before any other data","Verify the peer writes writeSignature(dataStreamProtocolSignature) or rpcStreamProtocolSignature as the very first 6 bytes on the stream","Check that no proxy/middleware consumes or rewrites the first bytes of the QUIC stream","Inspect the %v value in the message to identify what the peer actually sent"],"exampleFix":"// before: peer writes payload before the signature\nstream.Write([]byte(payload))\n// after: write the signature first\nif err := writeDataStreamPreamble(stream); err != nil {\n    return err\n}\nstream.Write([]byte(payload))","handlingStrategy":"validation","validationCode":"// Verify the peer's stream version matches before the handshake\nif clientVersion != serverVersion {\n    return fmt.Errorf(\"protocol version mismatch: client %s, server %s\", clientVersion, serverVersion)\n}","typeGuard":null,"tryCatchPattern":"if _, err := determineProtocol(stream); err != nil {\n    if strings.Contains(err.Error(), \"unknown signature\") {\n        // fall back or close stream and reconnect with a compatible peer\n        stream.Close()\n        return errIncompatibleProtocol\n    }\n    return err\n}","preventionTips":["Always write the 6-byte protocol signature as the first bytes of any new stream","Pin compatible cloudflared versions on both ends of the tunnel","Never interleave custom payload bytes before the signature preamble"],"tags":["quic","protocol-handshake","stream"],"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-14T00:17:10.932Z"}