{"record":{"id":"27e7f475b61572b9","repo":"hashicorp/nomad","slug":"root-key-algorithm-is-required","errorCode":null,"errorMessage":"root key algorithm is required","messagePattern":"root key algorithm is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/keyring.go","lineNumber":405,"sourceCode":"}\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\n// keystore with the AEAD KMS wrapper. This struct includes the server-specific\n// key-wrapping key (KEK). This struct should never be sent over RPC or written\n// to Raft.\ntype KeyEncryptionKeyWrapper struct {\n\tMeta *RootKeyMeta\n","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/keyring.go#L387-L423","documentation":"RootKeyMeta.Validate requires Algorithm to be non-empty. The algorithm determines how the root key is used for encryption (e.g. aes256-gcm), and downstream crypto code cannot proceed without it, so an empty algorithm fails validation.","triggerScenarios":"Upserting or rotating a root key where RootKeyMeta.Algorithm was never set (zero-value string) — for example building metadata manually instead of using structs.NewRootKeyMeta which sets a default algorithm.","commonSituations":"Hand-writing API payloads for /v1/operator/root-key that omit the algorithm field; older clients or scripts predating the algorithm field; copying metadata structs and clearing fields.","solutions":["Set Algorithm to a supported value such as structs.EncryptionAlgorithmAES256GCM.","Use structs.NewRootKeyMeta() which populates a default algorithm and key ID.","Add the algorithm field to your API request JSON if it was omitted."],"exampleFix":"// before\nmeta := &structs.RootKeyMeta{KeyID: keyID}\n// after\nmeta := &structs.RootKeyMeta{KeyID: keyID, Algorithm: structs.EncryptionAlgorithmAES256GCM}","handlingStrategy":"validation","validationCode":"if meta.Algorithm == \"\" {\n    return fmt.Errorf(\"Algorithm must be set (e.g. structs.EncryptionAlgorithmAES256GCM)\")\n}","typeGuard":null,"tryCatchPattern":"if err := meta.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"root key algorithm is required\") {\n        return fmt.Errorf(\"set RootKeyMeta.Algorithm before upserting a root key\")\n    }\n    return err\n}","preventionTips":["Use structs.NewRootKeyMeta() which sets a default algorithm","Define algorithm constants in one place in your tooling instead of raw strings","When marshaling metadata to JSON, ensure Algorithm has omitempty-free tags or explicit set"],"tags":["nomad","keyring","root-key","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"}