hashicorp/nomad · error
missing metadata
Error message
missing metadata
What it means
generateCipher requires a root key with populated metadata to pick the encryption algorithm and key ID. It throws "missing metadata" when the UnwrappedRootKey is nil or its Meta field is nil, since algorithm dispatch and key-ID tagging are impossible without it.
Source
Thrown at nomad/encrypter.go:658
// addCipher creates a new cipherSet for the key and stores them in the keyring
func (e *Encrypter) addCipher(rootKey *structs.UnwrappedRootKey) error {
generatedCipher, err := e.generateCipher(rootKey)
if err != nil {
return err
}
e.keyringLock.Lock()
defer e.keyringLock.Unlock()
e.keyring[rootKey.Meta.KeyID] = generatedCipher
return nil
}
func (e *Encrypter) generateCipher(rootKey *structs.UnwrappedRootKey) (*cipherSet, error) {
if rootKey == nil || rootKey.Meta == nil {
return nil, fmt.Errorf("missing metadata")
}
var wrapper kms.Wrapper
switch rootKey.Meta.Algorithm {
case structs.EncryptionAlgorithmAES256GCM:
wrapper = aead.NewWrapper()
_, err := wrapper.SetConfig(context.Background(),
aead.WithAeadType(kms.AeadTypeAesGcm),
aead.WithHashType(kms.HashTypeSha256),
aead.WithKey(rootKey.Key),
kms.WithKeyId(rootKey.Meta.KeyID),
)
if err != nil {
return nil, fmt.Errorf("could not configure cipher: %w", err)
}
default:
return nil, fmt.Errorf("invalid algorithm %s", rootKey.Meta.Algorithm)
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Verify the root key record includes its KeyMetadata (KeyID, Algorithm) in state before the keyring is loaded
- Rotate/re-create the affected key so a complete record with Meta is written
- Restore a known-good keyring snapshot
- If calling addCipher/generateCipher in tests or forks, always construct structs.UnwrappedRootKey with Meta set
Example fix
// before
rootKey := &structs.UnwrappedRootKey{Key: keyBytes}
err := e.generateCipher(rootKey)
// after
rootKey := &structs.UnwrappedRootKey{Key: keyBytes, Meta: &structs.RootKeyMeta{KeyID: kid, Algorithm: structs.EncryptionAlgorithmAES256GCM}}
err := e.generateCipher(rootKey) Defensive patterns
Strategy: validation
Validate before calling
func keyHasMeta(k *structs.UnwrappedRootKey) error {
if k == nil || k.Meta == nil { return errors.New("root key missing Meta") }
return nil
} Type guard
func hasMeta(k *structs.UnwrappedRootKey) bool { return k != nil && k.Meta != nil } Try / catch
if err != nil && err.Error() == "missing metadata" { /* rebuild or re-rotate the key record */ } Prevention
- Always construct UnwrappedRootKey with Meta populated (KeyID + Algorithm)
- Avoid hand-editing raft state or key records
- Verify keyring integrity after snapshot restore
When it happens
Trigger: addCipher is called with a root key whose Meta was never persisted, or a nil rootKey is passed (e.g. decrypt path yielded a zero-value struct).
Common situations: Corrupted or hand-edited raft/state key records; restoring snapshots produced by tooling that omitted the Meta block; programming errors calling generateCipher directly with an uninitialized key.
Related errors
- unable to decrypt wrapped key
- failed to configure keyring: %v
- failed to get active nomad key: %w
- rotated key does not exist in keyring: %w
- %w (root key): %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/3d36b16d1be0e051.
Report an issue: GitHub.