{"record":{"id":"f885213ecb178e09","repo":"hashicorp/nomad","slug":"root-key-metadata-is-required","errorCode":null,"errorMessage":"root key metadata is required","messagePattern":"root key metadata is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/keyring.go","lineNumber":399,"sourceCode":"}\n\n// IsInactive indicates that this key is no longer being used to encrypt new\n// variables or workload identities.\nfunc (rkm *RootKeyMeta) IsInactive() bool {\n\treturn rkm.State == RootKeyStateInactive || rkm.State == RootKeyStateDeprecated\n}\n\nfunc (rkm *RootKeyMeta) Copy() *RootKeyMeta {\n\tif rkm == nil {\n\t\treturn nil\n\t}\n\tout := *rkm\n\treturn &out\n}\n\nfunc (rkm *RootKeyMeta) Validate() error {\n\tif rkm == nil {\n\t\treturn fmt.Errorf(\"root key metadata is required\")\n\t}\n\tif rkm.KeyID == \"\" || !helper.IsUUID(rkm.KeyID) {\n\t\treturn fmt.Errorf(\"root key UUID is required\")\n\t}\n\tif rkm.Algorithm == \"\" {\n\t\treturn fmt.Errorf(\"root key algorithm is required\")\n\t}\n\tswitch rkm.State {\n\tcase RootKeyStateInactive, RootKeyStateActive,\n\t\tRootKeyStateRekeying, RootKeyStateDeprecated, RootKeyStatePrepublished:\n\tdefault:\n\t\treturn fmt.Errorf(\"root key state %q is invalid\", rkm.State)\n\t}\n\treturn nil\n}\n\n// KeyEncryptionKeyWrapper is a flattened version of the WrappedRootKeys struct\n// that gets serialized to disk for a keyset when using the legacy on-disk","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/keyring.go#L381-L417","documentation":"RootKeyMeta.Validate returns this error when the RootKeyMeta pointer itself is nil. Root key metadata (key ID, algorithm, state) must always accompany root key operations, so a nil metadata object is rejected outright. It is the first check in the validation chain, before UUID/algorithm/state checks.","triggerScenarios":"Calling keyring APIs (e.g. UPSERT/DELETE root key RPCs, keyring rotation, state store writes) with a nil *RootKeyMeta — typically when a caller forgets to construct metadata or a decode step produced a nil object.","commonSituations":"Hand-crafting API requests to /v1/operator/root-key endpoints and omitting the metadata; programmatic key rotation where RootKeyMeta was never initialized; decoding an empty/partial response and passing it onward.","solutions":["Construct and pass a valid RootKeyMeta (use structs.NewRootKeyMeta or similar constructor) before calling the keyring API.","Check for nil after any decode/deserialize step before invoking Validate or the RPC.","Verify the API request body actually includes the root key metadata fields."],"exampleFix":"// before\nvar meta *structs.RootKeyMeta\nerr := meta.Validate() // panics/errors: nil\n// after\nmeta := structs.NewRootKeyMeta()\nerr := meta.Validate()","handlingStrategy":"validation","validationCode":"if meta == nil {\n    meta = structs.NewRootKeyMeta()\n}\nif err := meta.Validate(); err != nil {\n    return err\n}","typeGuard":"func rootKeyMetaIsPresent(m *structs.RootKeyMeta) bool {\n    return m != nil\n}","tryCatchPattern":"if err := meta.Validate(); err != nil {\n    if err.Error() == \"root key metadata is required\" {\n        return fmt.Errorf(\"caller bug: RootKeyMeta must be initialized before keyring RPC\")\n    }\n    return err\n}","preventionTips":["Always construct metadata via structs.NewRootKeyMeta() rather than nil declarations","Check decode/unmarshal results for nil before passing onward","Use linters (nilness) to catch nil pointer flows into keyring calls"],"tags":["nomad","keyring","root-key","nil-validation"],"backgroundTag":"missing-root-key-metadata","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"}