golang/go · error
invalid length
Error message
invalid length
What it means
Sender.Export validates the requested output length against RFC 9180 §5.3, which limits the exporter output to a uint16 (0..65535 bytes). A negative length or any value above 0xFFFF is rejected before the KDF expand call.
Source
Thrown at src/crypto/hpke/hpke.go:199
// and then encrypts the provided plaintext like [Sender.Seal] (with no aad).
// Seal returns the concatenation of the encapsulated key and the ciphertext.
func Seal(pk PublicKey, kdf KDF, aead AEAD, info, plaintext []byte) ([]byte, error) {
enc, s, err := NewSender(pk, kdf, aead, info)
if err != nil {
return nil, err
}
ct, err := s.Seal(nil, plaintext)
if err != nil {
return nil, err
}
return append(enc, ct...), nil
}
// Export produces a secret value derived from the shared key between sender and
// recipient. length must be at most 65,535.
func (s *Sender) Export(exporterContext string, length int) ([]byte, error) {
if length < 0 || length > 0xFFFF {
return nil, errors.New("invalid length")
}
return s.export(exporterContext, uint16(length))
}
// Open decrypts the provided ciphertext, optionally binding to the additional
// public data aad, or returns an error if decryption fails.
//
// Open uses incrementing counters for each successful call, and must be called
// in the same order as Seal on the sending side.
func (r *Recipient) Open(aad, ciphertext []byte) ([]byte, error) {
if r.aead == nil {
return nil, errors.New("export-only instantiation")
}
plaintext, err := r.aead.Open(nil, r.nextNonce(), ciphertext, aad)
if err != nil {
return nil, err
}
r.seqNum++View on GitHub (pinned to b6b368adc5)
Solutions
- Clamp length to the [0, 65535] range before calling Export.
- Use a smaller, standard key size (16/32/64 bytes) for the derived secret.
- If you need more material, call Export multiple times with distinct exporterContext labels and concatenate.
Example fix
// before
secret, err := s.Export("label", 1<<20) // > 65535 -> error
// after
const maxLen = 0xFFFF
if length < 0 || length > maxLen {
return fmt.Errorf("export length %d out of range", length)
}
secret, err := s.Export("label", length) Defensive patterns
Strategy: validation
Validate before calling
const maxExporterLen = 0xFFFF
func export(s *hpke.Sender, label string, n int) ([]byte, error) {
if n < 0 || n > maxExporterLen {
return nil, fmt.Errorf("export length %d out of range [0,%d]", n, maxExporterLen)
}
return s.Export(label, n)
} Try / catch
secret, err := s.Export(label, n)
if err != nil {
if err.Error() == "invalid length" {
// clamp and retry with a safe default, or surface to caller
return s.Export(label, min(n, 0xFFFF))
}
return nil, err
} Prevention
- Use named constants for key sizes (e.g. const aesKeyLen = 32) instead of literals.
- Wrap Export in a helper that enforces the uint16 range once.
- Prefer deriving multiple shorter secrets over one oversized one.
When it happens
Trigger: Calling (*Sender).Export(exporterContext, length) with length < 0 or length > 0xFFFF (65535). Common when length is computed from a larger type (int) and the caller forgets the 16-bit cap.
Common situations: Deriving an oversized session key (e.g. asking for 128 KiB), passing -1 as a sentinel, or arithmetic that overflows int but is signed.
Related errors
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/fbd5111d25ccdaab.
Report an issue: GitHub.