ory/hydra · error

cookiex: cannot marshal cookie value

Error message

cookiex: cannot marshal cookie value

What it means

Returned by Codec.seal when json.Marshal of the caller's cookie value (type T) fails. The generic payload T contains a value that cannot be represented as JSON — e.g. a channel, func, cyclic reference, or unsupported map key type.

Source

Thrown at oryx/cookiex/cookiex.go:134

// envelope wraps the JSON payload with the seal time so decoding can enforce
// the max age.
type envelope struct {
	IssuedAt int64           `json:"iat"`
	Values   json.RawMessage `json:"v"`
}

// aad binds a ciphertext to this codec's purpose and the cookie name, so a
// sealed value cannot be replayed as a different cookie or in a different
// context, even under the same key.
func (c *Codec[T]) aad(name string) []byte {
	return []byte(aadPrefix + "|" + c.purpose + "|" + name)
}

func (c *Codec[T]) seal(name string, value T) (string, error) {
	payload, err := json.Marshal(value)
	if err != nil {
		return "", errors.Wrap(err, "cookiex: cannot marshal cookie value")
	}
	plaintext, err := json.Marshal(envelope{IssuedAt: c.now().Unix(), Values: payload})
	if err != nil {
		return "", errors.Wrap(err, "cookiex: cannot marshal envelope")
	}
	a, err := aead.New(c.keys[0])
	if err != nil {
		return "", errors.Wrap(err, "cookiex: cannot create AEAD")
	}
	// The nonce is prepended to the ciphertext. AEADs that manage the nonce
	// internally report a nonce size of zero, so this also covers them.
	nonce := make([]byte, a.NonceSize())
	if _, err := rand.Read(nonce); err != nil {
		return "", errors.Wrap(err, "cookiex: cannot generate nonce")
	}
	sealed := a.Seal(nonce, nonce, plaintext, c.aad(name))
	return formatPrefix + base64.RawURLEncoding.EncodeToString(sealed), nil
}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Make the cookie payload type T fully JSON-serializable (no funcs, channels, cycles, invalid map keys)
  2. Implement json.Marshaler on the offending type or store an ID/reference instead of the complex object
  3. Log the wrapped marshal error to identify which field fails serialization
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at oryx/cookiex/cookiex.go:134 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/ed29181a97328c00. Report an issue: GitHub.