{"record":{"id":"c7a602c475baf944","repo":"hashicorp/nomad","slug":"root-key-id-s-must-match-key-file-s","errorCode":null,"errorMessage":"root key ID %s must match key file %s","messagePattern":"root key ID (.+?) must match key file (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"nomad/encrypter.go","lineNumber":190,"sourceCode":"\t\tid, _, _ := strings.Cut(idWithIndex, \".\")\n\t\tif !helper.IsUUID(id) {\n\t\t\treturn nil\n\t\t}\n\n\t\te.keyringLock.RLock()\n\t\t_, ok := e.keyring[id]\n\t\te.keyringLock.RUnlock()\n\t\tif ok {\n\t\t\treturn nil // already loaded this key from another file\n\t\t}\n\n\t\tkey, err := e.loadKeyFromStore(path)\n\t\tif err != nil {\n\t\t\tkeyErrors[id] = fmt.Errorf(\"could not load key file %s from keystore: %w\", path, err)\n\t\t\treturn nil\n\t\t}\n\t\tif key.Meta.KeyID != id {\n\t\t\treturn fmt.Errorf(\"root key ID %s must match key file %s\", key.Meta.KeyID, path)\n\t\t}\n\n\t\terr = e.addCipher(key)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not add key file %s to keystore: %w\", path, err)\n\t\t}\n\n\t\t// we loaded this key from at least one KEK configuration, so clear any\n\t\t// error from a previous file that we couldn't read from\n\t\tdelete(keyErrors, id)\n\t\treturn nil\n\t})\n\n\tif len(keyErrors) == 0 {\n\t\treturn nil\n\t}\n\n\tvar mErr multierror.Error","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/encrypter.go#L172-L208","documentation":"The key file on disk decoded successfully, but its internal KeyID (key.Meta.KeyID) does not match the root key ID being processed (derived from the filename or keyring metadata). Nomad aborts keystore loading rather than silently binding key material to the wrong key ID.","triggerScenarios":"loadKeystore finds a .nks.json file whose embedded RootKey.Meta.KeyID differs from the id passed to the walker callback — typically after renaming a key file, copying the wrong file into the keystore, or a failed rotation left mismatched metadata.","commonSituations":"Operator renamed a key file manually, restored an inconsistent mix of keyring-metadata and key files from different snapshots, or copied a key file between clusters.","solutions":["Compare key.Meta.KeyID in the file (cat the .nks.json) with the expected ID from the filename/error message","Restore the correctly-named key file from backup or from a healthy server in the same region","Never rename .nks.json files manually; re-run key rotation instead of moving files","If the key is obsolete, remove it and the corresponding keyring metadata via nomad keyring rotate/remove"],"exampleFix":"// before: file renamed manually, ID mismatch\nmv data/keystore/WRONG-ID.nks.json data/keystore/EXPECTED-ID.nks.json\n// after: restore the correct key material for EXPECTED-ID from backup\nscp healthy-server:/opt/nomad/data/keystore/EXPECTED-ID.nks.json data/keystore/","handlingStrategy":"validation","validationCode":"// verify each key file's embedded ID matches its filename\nimport \"encoding/json\"\nfunc keyIDMatches(file string) (bool, error) {\n  b, err := os.ReadFile(file)\n  if err != nil { return false, err }\n  var k struct{ Meta struct{ KeyID string `json:\"KeyID\"` } `json:\"Meta\"` }\n  if err := json.Unmarshal(b, &k); err != nil { return false, err }\n  want := strings.TrimSuffix(filepath.Base(file), \".nks.json\")\n  return k.Meta.KeyID == want, nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only move key files between servers as a full keystore directory copy","Restore keyring metadata and key files from the same snapshot","Use nomad keyring commands instead of touching files for rotation","Audit keystore contents after any disaster-recovery restore"],"tags":["keyring","keystore","key-rotation","go"],"backgroundTag":"root-key-id-mismatch","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}