ory/hydra · error

cookiex: cannot bridge legacy cookie

Error message

cookiex: cannot bridge legacy cookie

What it means

Returned by openLegacy when marshaling the flattened legacy cookie map to JSON fails during bridging of a legacy securecookie value to the new format. Inputs are map[string]string already validated as strings, so a marshal failure is effectively unreachable and indicates an internal invariant break, not a bad cookie.

Solutions

  1. Inspect the wrapped json.Marshal error for the exact cause
  2. Verify the flattening loop only inserts string keys and values
  3. Treat as an internal error; do not expose details to the client
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at oryx/cookiex/legacy_securecookie.go:92 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/8d63e1daa9ec2200. Report an issue: GitHub.

Appendix: source

Thrown at oryx/cookiex/legacy_securecookie.go:92

	if len(c.legacy.codecs) == 0 {
		return zero, errors.WithStack(ErrInvalidCookie)
	}
	values := make(map[any]any)
	if err := securecookie.DecodeMulti(name, value, &values, c.legacy.codecs...); err != nil {
		return zero, errors.WithStack(ErrInvalidCookie)
	}
	flat := make(map[string]string, len(values))
	for k, v := range values {
		key, keyOK := k.(string)
		val, valOK := v.(string)
		if !keyOK || !valOK {
			return zero, errors.WithStack(ErrInvalidCookie)
		}
		flat[key] = val
	}
	bridge, err := json.Marshal(flat)
	if err != nil {
		return zero, errors.Wrap(err, "cookiex: cannot bridge legacy cookie")
	}
	var out T
	if err := json.Unmarshal(bridge, &out); err != nil {
		return zero, errors.WithStack(ErrInvalidCookie)
	}
	legacyDecodes.WithLabelValues(c.purpose).Inc()
	return out, nil
}

// WithLegacyEncode makes Set seal in the legacy securecookie format under the
// first legacy key pair, so pods that only understand the legacy format can
// read freshly minted cookies during a rolling deploy. Requires
// WithLegacyKeyPairs. This is stage 1 of the rollout; a follow-up removes the
// option, flipping encoding to the v1 format. JSON null values inside the
// payload are coerced to empty strings by the bridge; do not use pointer-typed
// fields while legacy encode is enabled.
func WithLegacyEncode() Option {
	return func(c *config) { c.legacyEncode = true }

View on GitHub (pinned to 4174065ffb)