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

  1. Clamp length to the [0, 65535] range before calling Export.
  2. Use a smaller, standard key size (16/32/64 bytes) for the derived secret.
  3. 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

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.