{"record":{"id":"d8d6549f3472ddd3","repo":"fatedier/frp","slug":"unsupported-message-codec","errorCode":null,"errorMessage":"unsupported message codec","messagePattern":"unsupported message codec","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proto/wire/wire.go","lineNumber":247,"sourceCode":"}\n\nfunc DefaultServerHello() ServerHello {\n\treturn ServerHello{\n\t\tSelected: ServerSelection{\n\t\t\tMessage: MessageSelection{\n\t\t\t\tCodec: MessageCodecJSON,\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc Supports(list []string, value string) bool {\n\treturn slices.Contains(list, value)\n}\n\nfunc ValidateClientHello(h ClientHello) error {\n\tif !Supports(h.Capabilities.Message.Codecs, MessageCodecJSON) {\n\t\treturn fmt.Errorf(\"unsupported message codec\")\n\t}\n\treturn ValidateCryptoCapabilities(h.Capabilities.Crypto)\n}\n","sourceCodeStart":229,"sourceCodeEnd":251,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/proto/wire/wire.go#L229-L251","documentation":"Thrown by ValidateClientHello when the client's advertised message codec list does not include MessageCodecJSON. JSON is the only message codec this implementation supports, so a ClientHello without it cannot be served. This runs on the server side when a client first connects.","triggerScenarios":"Client sends ClientHello with Capabilities.Message.Codecs empty or containing only non-JSON entries (e.g. [\"msgpack\"]); server calls ValidateClientHello during handshake acceptance.","commonSituations":"Third-party or custom clients omitting the Codecs field; older protocol versions that had no codec negotiation; test fixtures built by hand without the codec list.","solutions":["Always include wire.MessageCodecJSON in ClientHello.Capabilities.Message.Codecs — in practice send [MessageCodecJSON].","Fix hand-written ClientHello fixtures to populate the full capabilities struct.","Align custom clients with the stock frp client's hello construction."],"exampleFix":"// before\nhello.Capabilities.Message.Codecs = nil\n\n// after\nhello.Capabilities.Message.Codecs = []string{wire.MessageCodecJSON}","handlingStrategy":"validation","validationCode":"hello.Capabilities.Message.Codecs = []string{wire.MessageCodecJSON}\nif err := wire.ValidateClientHello(hello); err != nil {\n    return fmt.Errorf(\"hello rejected: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Populate capabilities from library constants, never from config strings.","Run ValidateClientHello client-side in a unit test to catch fixture drift."],"tags":["handshake","codec","protocol-negotiation","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}