{"record":{"id":"0ce775e4d685175b","repo":"nats-io/nats-server","slug":"unable-to-recover-keys","errorCode":null,"errorMessage":"unable to recover keys","messagePattern":"unable to recover keys","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"server/jetstream.go","lineNumber":331,"sourceCode":"\t\tns := kek.NonceSize()\n\t\tseed, err := kek.Open(nil, ekey[:ns], ekey[ns:], nil)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\taek, err := genEncryptionKey(prf.StoreCipher, seed)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif aek.NonceSize() != kek.NonceSize() {\n\t\t\tcontinue\n\t\t}\n\t\tplain, err := aek.Open(nil, buf[:ns], buf[ns:], nil)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\treturn plain, i > 0, nil\n\t}\n\treturn nil, false, fmt.Errorf(\"unable to recover keys\")\n}\n\n// Check to make sure directory has the jetstream directory.\n// We will have it properly configured here now regardless, so need to look inside.\nfunc (s *Server) checkStoreDir(cfg *JetStreamConfig) error {\n\tfis, _ := os.ReadDir(cfg.StoreDir)\n\t// If we have nothing underneath us, could be just starting new, but if we see this we can check.\n\tif len(fis) != 0 {\n\t\treturn nil\n\t}\n\t// Let's check the directory above. If it has us 'jetstream' but also other stuff that we can\n\t// identify as accounts then we can fix.\n\tfis, _ = os.ReadDir(filepath.Dir(cfg.StoreDir))\n\t// If just one that is us 'jetstream' and all is ok.\n\tif len(fis) == 1 {\n\t\treturn nil\n\t}\n","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream.go#L313-L349","documentation":"Returned by the JetStream encryption key recovery routine when none of the available key sources (TPM-sealed keys / pass-protected key file entries) could successfully open the encrypted key blob. Every candidate key failed to decrypt the stored key material.","triggerScenarios":"Recovering the JetStream encryption key at startup when the AES key file/TPM keys don't match the key that sealed the data (aek.Open fails for all i keys), e.g. keys were rotated, regenerated, or the store dir was moved between machines with different TPM keys.","commonSituations":"Regenerating the key file while old JetStream data remains on disk; moving storage directories between hosts; TPM key hierarchy changed (e.g. after clearing the TPM); wrong passphrase-supplied key entries.","solutions":["Restore the original key file / TPM keys used when the data was encrypted (from backup)","If data is disposable, delete the encrypted key and re-enable JetStream with a fresh key (data loss)","Check that the server's key/TPM configuration (JetStreamKey, JetStreamTpm.KeysFile) matches the machine and keys that sealed the data","Verify key file permissions and integrity (not truncated/edited)"],"exampleFix":"// before\n// keys file regenerated; old encrypted store present -> unable to recover keys\n// after\n// restore backed-up keys file:\n// cp /backup/nats/keys.json /etc/nats/jetstream-keys.json && systemctl restart nats-server","handlingStrategy":"validation","validationCode":"// Before starting the server, verify the key material matches the sealed store:\n// - confirm the JetStream key / TPM keys file is the same one used when the store was encrypted\n// - back it up and diff on deploy\nif _, err := os.Stat(keysFile); err != nil {\n    return fmt.Errorf(\"jetstream keys file missing: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Back up the encryption key file / TPM keys with the same care as the data","Never regenerate keys while encrypted JetStream data remains on disk","Avoid moving JetStream store dirs between machines with different TPMs","Document and version key rotation procedures with re-encryption steps"],"tags":["jetstream","encryption","tpm","key-recovery"],"backgroundTag":"jetstream-encryption-key-recovery-failed","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}