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

  1. Verify the root key record includes its KeyMetadata (KeyID, Algorithm) in state before the keyring is loaded
  2. Rotate/re-create the affected key so a complete record with Meta is written
  3. Restore a known-good keyring snapshot
  4. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/3d36b16d1be0e051. Report an issue: GitHub.