{"record":{"id":"b1b1e230e0f357b4","repo":"ory/hydra","slug":"at-least-one-encryption-key-must-be-defined-but-no","errorCode":null,"errorMessage":"at least one encryption key must be defined but none were","messagePattern":"at least one encryption key must be defined but none were","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"aead/helpers.go","lineNumber":38,"sourceCode":"\t}\n\n\treturn key, nil\n}\n\nfunc allKeys(ctx context.Context, d Dependencies) ([][]byte, error) {\n\tglobal, err := d.GetGlobalSecret(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trotated, err := d.GetRotatedGlobalSecrets(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tkeys := append([][]byte{global}, rotated...)\n\tif len(keys) == 0 {\n\t\treturn nil, fmt.Errorf(\"at least one encryption key must be defined but none were\")\n\t}\n\treturn keys, nil\n}\n","sourceCodeStart":20,"sourceCodeEnd":42,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/aead/helpers.go#L20-L42","documentation":"allKeys collects the global (current) AEAD key plus rotated keys and refuses to proceed when none are configured. Decrypt and encryptionKey depend on this list, so decryption/encryption cannot run without at least one key.","triggerScenarios":"Calling Decrypt or Encrypt when the AEAD dependency has an empty global key and no rotated keys (e.g. secrets.system unset or empty in configuration).","commonSituations":"Forgetting to set SECRETS_SYSTEM when deploying Hydra; empty string after config parsing; a fresh instance without the key used to encrypt previously stored data; environment variables not loaded in container orchestration.","solutions":["Set secrets.system / SECRETS_SYSTEM to a non-empty base64 32-byte key (openssl rand -base64 32).","When moving deployments, keep the original key in rotated_keys so existing ciphertexts remain decryptable.","Verify the environment variable actually reaches the process (docker-compose env, k8s secret mounted, config file loaded with -c).","If data is unrecoverable, accept invalidation: reset the key and re-create affected secrets."],"exampleFix":"// before (docker-compose)\nenvironment: []\n\n// after\nenvironment:\n  - SECRETS_SYSTEM=Q7N3...base64-32-bytes...","handlingStrategy":"validation","validationCode":"// Before starting the service/janitor:\nif os.Getenv(\"SECRETS_SYSTEM\") == \"\" {\n    panic(\"SECRETS_SYSTEM must be set (base64 32-byte key): openssl rand -base64 32\")\n}","typeGuard":null,"tryCatchPattern":"// Wrap decryption so a missing-key config surfaces clearly:\nval, err := x.Decrypt(ctx, ct)\nif err != nil {\n    return nil, fmt.Errorf(\"decrypt failed — is secrets.system configured and matching the key that encrypted this data? %w\", err)\n}","preventionTips":["Set SECRETS_SYSTEM in every environment before first boot and persist it.","Back up the key; losing it makes encrypted data undecryptable.","In orchestrators, mount the key via a secret and fail fast on empty values.","Use rotated_keys when migrating deployments."],"tags":["encryption","aead","configuration","key-management"],"backgroundTag":"missing-encryption-key","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}