{"record":{"id":"58e60b5ec63b6e42","repo":"fatedier/frp","slug":"selected-udp-packet-codec-was-not-advertised-by-cl","errorCode":null,"errorMessage":"selected UDP packet codec was not advertised by client: %s","messagePattern":"selected UDP packet codec was not advertised by client: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/proto/wire/crypto.go","lineNumber":102,"sourceCode":"\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 {\n\t\treturn fmt.Errorf(\"invalid crypto server random length %d, want %d\", len(cryptoSelection.ServerRandom), CryptoRandomSize)\n\t}\n\treturn nil\n}\n\nfunc selectUDPPacketCodec(codecs []string) string {\n\tif Supports(codecs, UDPPacketCodecBinary) {\n\t\treturn UDPPacketCodecBinary","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/proto/wire/crypto.go#L84-L120","documentation":"Thrown by ValidateServerHelloForClient when the ServerHello selects UDP packet codec \"binary\" but the client never advertised that codec in ClientHello.Capabilities.Message.UDPPacketCodecs. This guards against a server unilaterally enabling a feature the client did not offer, which would break the client's ability to decode UDP packets.","triggerScenarios":"Client sends ClientHello with UDPPacketCodecs empty (or lacking \"binary\"), and the server responds with Selected.Message.UDPPacketCodec = \"binary\". Validation via Supports(clientHello.Capabilities.Message.UDPPacketCodecs, udpPacketCodec) fails.","commonSituations":"A server bug that ignores the client's advertised capabilities; a custom client that wants to opt out of the binary UDP codec but talks to a stock server that assumes support; mismatched test hello fixtures where the client hello and server hello are built independently.","solutions":["On the client, include wire.UDPPacketCodecBinary in ClientHello.Capabilities.Message.UDPPacketCodecs when binary UDP encoding is acceptable.","On the server, derive the selection with selectUDPPacketCodec(clientHello.Capabilities.Message.UDPPacketCodecs) instead of hardcoding it.","In tests, generate the server hello from the same client hello object that is sent."],"exampleFix":"// before (server)\nselected.UDPPacketCodec = wire.UDPPacketCodecBinary // hardcoded\n\n// after\nselected.UDPPacketCodec = selectUDPPacketCodec(clientHello.Capabilities.Message.UDPPacketCodecs)","handlingStrategy":"validation","validationCode":"// client side: advertise binary support if you can handle it\nhello.Capabilities.Message.UDPPacketCodecs = append(\n    hello.Capabilities.Message.UDPPacketCodecs, wire.UDPPacketCodecBinary)\n\n// server side: only echo what the client offered\nif !wire.Supports(clientHello.Capabilities.Message.UDPPacketCodecs, wire.UDPPacketCodecBinary) {\n    selected.UDPPacketCodec = \"\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive every server selection from the client's advertised capability lists.","In e2e tests, generate the server hello from the exact client hello struct that was serialized."],"tags":["handshake","udp","capabilities","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}