# X_SEAL_INVALID

## Means

a sealed value did not authenticate, or is not a sealed value

## Typical cause

the string is not `x1.<keyId>.<iv>.<ciphertext>` (never sealed, or truncated), or the AES-256-GCM tag rejected it under a key whose id matched: it was sealed for a different `purpose`, or its bytes changed. AEAD cannot tell those two apart, so the cause names both. Never garbage, never the raw string back

## Fix

`x secrets show --json` — confirms the key id in force; a value that failed its tag is unrecoverable and must be re-entered. Never sealed (a column sealed after rows were written): add a new `.sealed()` column, copy with a `backfill()`, drop the old one — [Entities and migrations](/entities-and-migrations)

[Encrypted secrets](/error-codes#encrypted-secrets)
