hashicorp/nomad · error

unable to create key wrapper: %w

Error message

unable to create key wrapper: %w

What it means

encryptDEK builds the KMS wrapper via newKMSWrapper for the configured provider (Vault Transit, AWS KMS, Azure KeyVault, PKCS11, or AEAD). If wrapper construction fails — bad provider config, missing credentials, unreachable endpoint — the error is wrapped as "unable to create key wrapper". No root key wrapping can proceed without a working wrapper.

Source

Thrown at nomad/encrypter.go:870

// encryptDEK encrypts the DEKs (one for encryption and one for signing) with
// the KMS provider and returns a WrappedKey built from the provider's
// kms.BlobInfo. This includes the cleartext KEK for the AEAD provider.
func (e *Encrypter) encryptDEK(rootKey *structs.UnwrappedRootKey, provider *structs.KEKProviderConfig) (*structs.WrappedKey, error) {
	if provider == nil {
		panic("can't encrypt DEK without a provider")
	}
	var kek []byte
	var err error
	if provider.Provider == structs.KEKProviderAEAD || provider.Provider == "" {
		kek, err = crypto.Bytes(32)
		if err != nil {
			return nil, fmt.Errorf("failed to generate key wrapper key: %w", err)
		}
	}
	wrapper, err := e.newKMSWrapper(provider, rootKey.Meta.KeyID, kek)
	if err != nil {
		return nil, fmt.Errorf("unable to create key wrapper: %w", err)
	}

	rootBlob, err := wrapper.Encrypt(e.srv.shutdownCtx, rootKey.Key)
	if err != nil {
		return nil, fmt.Errorf("failed to encrypt root key: %w", err)
	}

	kekWrapper := &structs.WrappedKey{
		Provider:                 provider.Provider.String(),
		ProviderID:               provider.ID(),
		WrappedDataEncryptionKey: rootBlob,
		WrappedRSAKey:            &kms.BlobInfo{},
		KeyEncryptionKey:         kek,
	}

	// Only cipherSets created after 1.7.0 will contain an RSA key.
	if len(rootKey.RSAKey) > 0 {
		rsaBlob, err := wrapper.Encrypt(e.srv.shutdownCtx, rootKey.RSAKey)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the wrapped cause: fix the provider configuration fields the inner error names (key_id, endpoint, region, etc.).
  2. Verify credentials/env vars for the provider (VAULT_TOKEN, AWS credentials, Azure creds) are present on the Nomad server.
  3. Confirm the provider name is valid and the external KMS plugin (if used) is installed and executable.
  4. Test connectivity to the KMS endpoint (Vault, AWS KMS, Azure KeyVault) from the server host.

Example fix

// before
kms_config {
  provider = "awskms"
  config { key_id = "alias/wrong-key" }
}
// after
kms_config {
  provider = "awskms"
  config { key_id = "alias/nomad-default" region = "us-east-1" endpoint = "kms.us-east-1.amazonaws.com" }
}
Defensive patterns

Strategy: validation

Validate before calling

// before wrapping, validate the kms_config is complete and provider is known
if provider == "" {
    return errors.New("kms provider must be set")
}
// e.g. for awskms: check key_id and region are non-empty in config

Type guard

func validKMSConfig(p string, cfg map[string]string) bool {
    switch p {
    case "awskms":
        return cfg["kms_key_id"] != "" && cfg["region"] != ""
    case "vault":
        return cfg["vault_address"] != "" && cfg["transit_key"] != ""
    case "aead":
        return true
    default:
        return false
    }
}

Try / catch

wrapper, err := encryptDEK(...)
if err != nil && strings.Contains(err.Error(), "unable to create key wrapper") {
    // log full wrapped chain; fix provider config before retrying
}

Prevention

When it happens

Trigger: newKMSWrapper(provider, rootKey.Meta.KeyID, kek) returns an error while wrapping a root key — e.g., invalid kms config struct, unknown provider name, or provider constructor failing (bad key ID, missing config fields).

Common situations: Misconfigured kms block in server config (wrong key_id, region, vault address); missing provider credentials; typo'd provider name; KMS plugin binary missing or fails to launch.

Related errors


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