hashicorp/nomad · error

unable to create KMS wrapper for provider

Error message

unable to create KMS wrapper for provider %q: %w

What it means

A matching KMS provider config exists, but newKMSWrapper could not construct the go-kms-wrapping wrapper for it — bad credentials, missing required fields, or failed backend initialization. The underlying error is deliberately wrapped with the provider ID because raw library errors are opaque.

Solutions

  1. Read the wrapped cause (%w) for the specific library error from the KMS SDK
  2. Validate the provider's required fields in the kms config block (kms_key_id, endpoint, region, etc.)
  3. Check cloud credentials on the server (instance profile, env vars, workload identity) and Vault token validity for transit
  4. Test the provider independently (aws kms describe-key, vault status) then restart the agent

Example fix

// before: kms block missing kms_key_id
kms = { provider = "awskms" region = "us-east-1" }
// after
kms = {
  provider   = "awskms"
  kms_key_id = "alias/nomad-key"
  region     = "us-east-1"
}
Defensive patterns

Strategy: validation

Validate before calling

// smoke-test the provider before the agent needs it
// awskms: aws kms describe-key --key-id alias/nomad-key --region us-east-1
// transit: vault token lookup  &&  vault status
// gcpckms: gcloud kms keys describe nomad-key --keyring=... --location=...
if err := probeProvider("awskms"); err != nil {
  return fmt.Errorf("KMS provider unreachable, wrapper creation would fail: %w", err)
}

Try / catch

if err := srv.AddWrappedKey(wrappedKeys); err != nil {
  if strings.Contains(err.Error(), "unable to create KMS wrapper") {
    return fmt.Errorf("check KMS credentials and required config fields for this provider, then restart agent: %w", err)
  }
  return err
}

Prevention

When it happens

Trigger: AddWrappedKey resolves the provider config and calls e.newKMSWrapper(provider, wrappedKeys.KeyID, wrappedKey.KeyEncryptionKey); wrapper construction fails on missing/invalid options (e.g. no kms_key_id, invalid Vault token, bad GCP/Azure credentials).

Common situations: Incomplete kms block in server config, expired Vault token for transit, IAM credentials not present on the server host, wrong region/endpoint, or env vars (AWS_*, GOOGLE_*, AZURE_*) absent in the agent's environment.

Related errors


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

Appendix: source

Thrown at nomad/encrypter.go:487

	for _, wrappedKey := range wrappedKeys.WrappedKeys {
		providerID := wrappedKey.ProviderID
		if providerID == "" {
			providerID = string(structs.KEKProviderAEAD)
		}

		provider, ok := e.providerConfigs[providerID]
		if !ok {
			err := fmt.Errorf("no such KMS provider %q configured", providerID)
			mErr = multierror.Append(mErr, err)
			continue
		}

		wrapper, err := e.newKMSWrapper(provider, wrappedKeys.KeyID, wrappedKey.KeyEncryptionKey)
		if err != nil {
			// the errors that bubble up from this library can be a bit opaque, so
			// make sure we wrap them with as much context as possible
			err := fmt.Errorf("unable to create KMS wrapper for provider %q: %w", providerID, err)
			mErr = multierror.Append(mErr, err)
			continue
		}

		// fan-out decryption tasks for HA in Nomad Enterprise. we can use the
		// key whenever any one provider returns a successful decryption.
		go e.decryptWrappedKeyTask(completeCtx, wrapper, wrappedKeys.Meta(), wrappedKey, cipherSetCh)
		decryptTasks++
	}

	if err := mErr.ErrorOrNil(); err != nil {

		// If we have no tasks running, we can log an error for the operator and
		// exit.
		//
		// It is likely any decryption configuration for the key is incorrect
		// and follow-up attempts from other Raft/FMS calls for this key will
		// also fail. We should not, however, continue with the server startup

View on GitHub (pinned to 482b49bf1a)