hashicorp/nomad · error
Secret %q has provider "vault" but no vault block
Error message
Secret %q has provider "vault" but no vault block
What it means
A task secret whose provider is "vault" requires the task (or task group) to have a vault block so Nomad can obtain a Vault token; Task.Validate emits this error when s.Provider == SecretProviderVault and t.Vault == nil.
Source
Thrown at nomad/structs/structs.go:8453
if wid.Name == WorkloadIdentityDefaultName {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Duplicate default identities found"))
}
if err := wid.Validate(); err != nil {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Identity %q is invalid: %w", wid.Name, err))
}
}
secrets := make(map[string]bool)
for _, s := range t.Secrets {
if _, ok := secrets[s.Name]; ok {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Duplicate secret %q found", s.Name))
} else {
secrets[s.Name] = true
}
if s.Provider == SecretProviderVault && t.Vault == nil {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Secret %q has provider \"vault\" but no vault block", s.Name))
}
if err := s.Validate(); err != nil {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Secret %q is invalid: %w", s.Name, err))
}
}
return mErr.ErrorOrNil()
}
// validateServices takes a task and validates the services within it are valid
// and reference ports that exist.
func validateServices(t *Task, tgNetworks Networks) error {
var mErr multierror.Error
// Ensure that services don't ask for nonexistent ports and their names are
// unique.
servicePorts := make(map[string]map[string]struct{})View on GitHub (pinned to 482b49bf1a)
Solutions
- Add a vault { } block (group or task level) to the job granting the needed policies
- Change the secret's provider to a non-vault provider if Vault is not actually used
- If the cluster uses workload identity-based Vault auth, ensure the vault block plus identity aud are configured per Nomad version docs
Example fix
// before
secrets {
name = "db_password"
provider = "vault"
path = "kv/data/db"
}
// after
vault {}
secrets {
name = "db_password"
provider = "vault"
path = "kv/data/db"
} Defensive patterns
Strategy: validation
Validate before calling
for _, s := range t.Secrets {
if s.Provider == "vault" && t.Vault == nil {
return fmt.Errorf("secret %q uses provider vault; add a vault block", s.Name)
}
} Prevention
- Always pair vault-provider secrets with a vault { } block in the job
- When migrating off the legacy vault stanza, keep the vault block for secrets usage
- Check group-level vault inheritance in the Nomad version you run
When it happens
Trigger: Task defines secrets { name=..., provider = "vault", ... } but has no vault { } block anywhere in the job/group/task; job migrated to the secrets block syntax while the legacy vault integration block was removed.
Common situations: Migrating from legacy Vault stanza to the new secrets/provider model and dropping vault blocks; assuming a cluster-level Vault connection suffices (a per-job vault block is still required); partial template rendering that drops the vault block.
Related errors
- namespace cannot contain template delimiters or parenthesis
- secret path cannot contain template delimiters or parenthesi
- secret name cannot be empty
- secret provider cannot be empty
- secret path cannot be empty
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/222071d543d3b4ac.
Report an issue: GitHub.