caddyserver/caddy · error
parsing public_key: %w
Error message
parsing public_key: %w
What it means
After the KEM check, UnmarshalBinary parses the public_key field via the KEM scheme's UnmarshalBinaryPublicKey. Malformed or wrong-length key bytes (not a valid X25519 public key) produce this wrapped error. For X25519 the expected length is exactly 32 bytes, so truncated or expanded blobs fail here.
Source
Thrown at modules/caddytls/ech.go:1001
var t cryptobyte.String
var pk []byte
if !content.ReadUint8(&echCfg.ConfigID) ||
!content.ReadUint16((*uint16)(&echCfg.KEMID)) ||
!content.ReadUint16LengthPrefixed(&t) ||
!t.ReadBytes(&pk, len(t)) ||
!content.ReadUint16LengthPrefixed(&t) ||
len(t)%4 != 0 /* the length of (KDFs and AEADs) must be divisible by 4 */ {
return errInvalidLen
}
if !echCfg.KEMID.IsValid() {
return fmt.Errorf("invalid KEM ID: %d", echCfg.KEMID)
}
var err error
if echCfg.PublicKey, err = echCfg.KEMID.Scheme().UnmarshalBinaryPublicKey(pk); err != nil {
return fmt.Errorf("parsing public_key: %w", err)
}
echCfg.CipherSuites = echCfg.CipherSuites[:0]
for !t.Empty() {
var hpkeKDF, hpkeAEAD uint16
if !t.ReadUint16(&hpkeKDF) || !t.ReadUint16(&hpkeAEAD) {
// we have already checked that the length is divisible by 4
panic("this must not happen")
}
if !hpke.KDF(hpkeKDF).IsValid() {
return fmt.Errorf("invalid KDF ID: %d", hpkeKDF)
}
if !hpke.AEAD(hpkeAEAD).IsValid() {
return fmt.Errorf("invalid AEAD ID: %d", hpkeAEAD)
}
echCfg.CipherSuites = append(echCfg.CipherSuites, hpkeSymmetricCipherSuite{
KDFID: hpke.KDF(hpkeKDF),View on GitHub (pinned to 50e54ee279)
Solutions
- Delete the suspect ech/configs/<id>/config.bin (whole ID directory) so Caddy mints a fresh config.
- If importing, ensure the public key is a raw 32-byte X25519 key inside the ECHConfig structure.
- Check storage reliability if files keep truncating.
Defensive patterns
Strategy: validation
Try / catch
if err != nil && strings.Contains(err.Error(), "parsing public_key") {
// corrupt stored config: delete ech/configs/<id> and restart to regenerate
} Prevention
- Use atomic/copy-safe storage migration for the Caddy data dir.
- Regenerate rather than repair ECH configs — they are cheap and rotate by design.
When it happens
Trigger: Stored ECH config where the length-prefixed public key blob is not 32 bytes or not a valid curve point encoding — corruption, wrong-version data, or a config list crafted for another KEM.
Common situations: Truncated config.bin from an interrupted storage write; storage backend with byte-mangling bugs; hand-assembled ECH configs for testing.
Related errors
- invalid KEM ID: %d
- invalid KDF ID: %d
- invalid AEAD ID: %d
- marshaling ECH private key: %v
- marshaling ECH config: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/eea640b4469286ef.
Report an issue: GitHub.