hashicorp/nomad · error
Task %s uses Vault cluster %s but does not have an identity
Error message
Task %s uses Vault cluster %s but does not have an identity named %s and no default identity is provided in agent configuration
What it means
Tasks that use a non-default Vault cluster (t.Vault.Cluster != structs.VaultDefaultCluster) must carry a workload identity named via t.Vault.IdentityName(). If no such identity exists on the task and no default identity is supplied in agent configuration, validation fails because Nomad cannot determine which Vault identity/cluster credentials to use for the task.
Source
Thrown at nomad/job_endpoint_hooks.go:605
for _, wid := range t.Identities {
if strings.HasPrefix(wid.Name, structs.WorkloadIdentityVaultPrefix) {
warnings = append(warnings, fmt.Errorf("Task %s has an identity called %s but no vault block", t.Name, wid.Name))
}
}
return warnings, nil
}
vaultWIDName := t.Vault.IdentityName()
vaultWID := t.GetIdentity(vaultWIDName)
if vaultWID != nil && !okForIdentity {
return warnings, fmt.Errorf("Task %s cannot have an identity for Vault until all servers are upgraded to %s or later", t.Name, minVersionMultiIdentities)
}
if vaultWID == nil {
// Tasks using non-default clusters are required to have an identity.
if t.Vault.Cluster != structs.VaultDefaultCluster {
return warnings, fmt.Errorf(
"Task %s uses Vault cluster %s but does not have an identity named %s and no default identity is provided in agent configuration",
t.Name, t.Vault.Cluster, vaultWIDName,
)
}
return warnings, nil
}
return warnings, nil
}
type memoryOversubscriptionValidate struct {
srv *Server
}
func (*memoryOversubscriptionValidate) Name() string {
return "memory_oversubscription"
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Add an identity block named t.Vault.IdentityName() (e.g. name = "vault_<cluster>") to the task
- Configure a default Vault identity in the Nomad agent configuration
- Remove the vault.cluster override to use the default cluster, which does not require an explicit identity
Example fix
// before
vault { cluster = "prod-vault" } // no identity
// after
vault { cluster = "prod-vault" }
identity { name = "vault_prod-vault" aud = ["vault.io/audience/prod"] env = false file = true } Defensive patterns
Strategy: validation
Validate before calling
// before submit
if task.Vault != nil && task.Vault.Cluster != "default" {
names := identityNames(task.Identities)
if !contains(names, "vault_"+task.Vault.Cluster) {
return fmt.Errorf("task %s needs identity vault_%s", task.Name, task.Vault.Cluster)
}
} Prevention
- Always pair non-default vault.cluster with a matching identity block
- Lint job HCL for vault cluster/identity pairing before running
- Verify identity name matches t.Vault.IdentityName() exactly (cluster-suffixed)
When it happens
Trigger: Submitting a job where a task sets vault.cluster = "my-cluster" (non-default) but defines no identity with the Vault identity name and no default identity is configured agent-side. Raised in validateVaultIdentity when vaultWID == nil.
Common situations: Misconfigured job spec referencing an alternate Vault cluster without the required identity block; forgetting that non-default clusters mandate identities; typo in identity name so GetIdentity lookup misses; agent config lacking the default identity.
Related errors
- Task %s cannot have an identity for Vault until all servers
- no signed workload identity available
- non-default Vault cluster requires Nomad Enterprise
- failed to retrieve signed workload identity: %w
- Vault %q not enabled but used in the job
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/d901800ffb16d5d4.
Report an issue: GitHub.