fatedier/frp · error
unsupported selected message codec: %s
Error message
unsupported selected message codec: %s
What it means
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.
Source
Thrown at pkg/proto/wire/crypto.go:94
ServerRandom: serverRandom,
},
},
}, nil
}
func ValidateCryptoCapabilities(c CryptoCapabilities) error {
if len(c.ClientRandom) != CryptoRandomSize {
return fmt.Errorf("invalid crypto client random length %d, want %d", len(c.ClientRandom), CryptoRandomSize)
}
if _, ok := SelectAEADAlgorithm(c.Algorithms); !ok {
return fmt.Errorf("no supported crypto algorithm")
}
return nil
}
func ValidateServerHelloForClient(clientHello ClientHello, serverHello ServerHello) error {
if serverHello.Selected.Message.Codec != MessageCodecJSON {
return fmt.Errorf("unsupported selected message codec: %s", serverHello.Selected.Message.Codec)
}
udpPacketCodec := serverHello.Selected.Message.UDPPacketCodec
if udpPacketCodec != "" {
if udpPacketCodec != UDPPacketCodecBinary {
return fmt.Errorf("unsupported selected UDP packet codec: %s", udpPacketCodec)
}
if !Supports(clientHello.Capabilities.Message.UDPPacketCodecs, udpPacketCodec) {
return fmt.Errorf("selected UDP packet codec was not advertised by client: %s", udpPacketCodec)
}
}
cryptoSelection := serverHello.Selected.Crypto
if !IsSupportedAEADAlgorithm(cryptoSelection.Algorithm) {
return fmt.Errorf("unknown selected crypto algorithm: %s", cryptoSelection.Algorithm)
}
if !Supports(clientHello.Capabilities.Crypto.Algorithms, cryptoSelection.Algorithm) {
return fmt.Errorf("selected crypto algorithm was not advertised by client: %s", cryptoSelection.Algorithm)
}
if len(cryptoSelection.ServerRandom) != CryptoRandomSize {View on GitHub (pinned to 6c8a8d0a97)
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.
Example fix
// before (test/mock) serverHello.Selected.Message.Codec = "msgpack" // after serverHello.Selected.Message.Codec = wire.MessageCodecJSON
Defensive patterns
Strategy: validation
Validate before calling
if serverHello.Selected.Message.Codec != wire.MessageCodecJSON {
// reject before building crypto context
return fmt.Errorf("bad codec %q", serverHello.Selected.Message.Codec)
} Try / catch
if err := wire.ValidateServerHelloForClient(clientHello, serverHello); err != nil {
// treat connection as untrusted/broken: close, do not retry on same conn
conn.Close()
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- unsupported selected UDP packet codec: %s
- unsupported message codec
- unknown selected crypto algorithm: %s
- serverHello.Error
- no supported crypto algorithm
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/d20b20ba1aaa0b28.
Report an issue: GitHub.