{"record":{"id":"d20b20ba1aaa0b28","repo":"fatedier/frp","slug":"unsupported-selected-message-codec-s","errorCode":null,"errorMessage":"unsupported selected message codec: %s","messagePattern":"unsupported selected message codec: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proto/wire/crypto.go","lineNumber":94,"sourceCode":"\t\t\t\tServerRandom: serverRandom,\n\t\t\t},\n\t\t},\n\t}, nil\n}\n\nfunc ValidateCryptoCapabilities(c CryptoCapabilities) error {\n\tif len(c.ClientRandom) != CryptoRandomSize {\n\t\treturn fmt.Errorf(\"invalid crypto client random length %d, want %d\", len(c.ClientRandom), CryptoRandomSize)\n\t}\n\tif _, ok := SelectAEADAlgorithm(c.Algorithms); !ok {\n\t\treturn fmt.Errorf(\"no supported crypto algorithm\")\n\t}\n\treturn nil\n}\n\nfunc ValidateServerHelloForClient(clientHello ClientHello, serverHello ServerHello) error {\n\tif serverHello.Selected.Message.Codec != MessageCodecJSON {\n\t\treturn fmt.Errorf(\"unsupported selected message codec: %s\", serverHello.Selected.Message.Codec)\n\t}\n\tudpPacketCodec := serverHello.Selected.Message.UDPPacketCodec\n\tif udpPacketCodec != \"\" {\n\t\tif udpPacketCodec != UDPPacketCodecBinary {\n\t\t\treturn fmt.Errorf(\"unsupported selected UDP packet codec: %s\", udpPacketCodec)\n\t\t}\n\t\tif !Supports(clientHello.Capabilities.Message.UDPPacketCodecs, udpPacketCodec) {\n\t\t\treturn fmt.Errorf(\"selected UDP packet codec was not advertised by client: %s\", udpPacketCodec)\n\t\t}\n\t}\n\tcryptoSelection := serverHello.Selected.Crypto\n\tif !IsSupportedAEADAlgorithm(cryptoSelection.Algorithm) {\n\t\treturn fmt.Errorf(\"unknown selected crypto algorithm: %s\", cryptoSelection.Algorithm)\n\t}\n\tif !Supports(clientHello.Capabilities.Crypto.Algorithms, cryptoSelection.Algorithm) {\n\t\treturn fmt.Errorf(\"selected crypto algorithm was not advertised by client: %s\", cryptoSelection.Algorithm)\n\t}\n\tif len(cryptoSelection.ServerRandom) != CryptoRandomSize {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/proto/wire/crypto.go#L76-L112","documentation":"Thrown by ValidateServerHelloForClient when the ServerHello's selected message codec is not MessageCodecJSON (\"json\"). The wire protocol currently supports JSON as the only message codec, so any other selection is a protocol violation. It fires on the client side after receiving the server's hello during handshake validation.","triggerScenarios":"A malicious, buggy, or version-mismatched server sends ServerHello with Selected.Message.Codec set to anything other than \"json\" (or a codec string the client does not know). NewClientCryptoContext decodes both hello payloads and calls ValidateServerHelloForClient, which raises this error.","commonSituations":"Connecting a client to a server from a different frp version that introduced a new message codec; test mocks that build ServerHello by hand and forget to set the codec field; a man-in-the-middle or corrupted connection producing garbage JSON that decodes to a zero/unknown codec.","solutions":["Ensure the server only selects codecs the client advertised; the server should echo MessageCodecJSON from the client's ClientHello.","Fix hand-built ServerHello fixtures in tests to set Selected.Message.Codec = MessageCodecJSON.","Run matching frp versions on both ends of the connection."],"exampleFix":"// before (test/mock)\nserverHello.Selected.Message.Codec = \"msgpack\"\n\n// after\nserverHello.Selected.Message.Codec = wire.MessageCodecJSON","handlingStrategy":"validation","validationCode":"if serverHello.Selected.Message.Codec != wire.MessageCodecJSON {\n    // reject before building crypto context\n    return fmt.Errorf(\"bad codec %q\", serverHello.Selected.Message.Codec)\n}","typeGuard":null,"tryCatchPattern":"if err := wire.ValidateServerHelloForClient(clientHello, serverHello); err != nil {\n    // treat connection as untrusted/broken: close, do not retry on same conn\n    conn.Close()\n    return err\n}","preventionTips":["Build ServerHello fixtures via the library's own constructors so the codec field is always correct.","Never construct Selected.Message by hand in application code."],"tags":["handshake","protocol-negotiation","codec","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}