hashicorp/nomad · error
Identity %q is invalid: %w
Error message
Identity %q is invalid: %w
What it means
When a task declares a default identity block, Task.Validate calls WorkloadIdentity.Validate and wraps any failure as 'Identity %q is invalid: %w'. The inner error comes from the identity's own validation (missing name is impossible for the default, so usually audience/expiration/TTL problems).
Source
Thrown at nomad/structs/structs.go:8427
mErr.Errors = append(mErr.Errors, fmt.Errorf("CSIPluginConfig must have a non-empty PluginID"))
}
if !CSIPluginTypeIsValid(t.CSIPluginConfig.Type) {
mErr.Errors = append(mErr.Errors, fmt.Errorf("CSIPluginConfig PluginType must be one of 'node', 'controller', or 'monolith', got: \"%s\"", t.CSIPluginConfig.Type))
}
if t.CSIPluginConfig.StagePublishBaseDir != "" && t.CSIPluginConfig.MountDir != "" &&
helper.IsSubdirectory(t.CSIPluginConfig.MountDir, t.CSIPluginConfig.StagePublishBaseDir) {
mErr.Errors = append(mErr.Errors, fmt.Errorf("CSIPluginConfig StagePublishBaseDir must not be a subdirectory of MountDir, got: StagePublishBaseDir=\"%s\" MountDir=\"%s\"", t.CSIPluginConfig.StagePublishBaseDir, t.CSIPluginConfig.MountDir))
}
// TODO: Investigate validation of the PluginMountDir. Not much we can do apart from check IsAbs until after we understand its execution environment though :(
}
// Validate default Identity
if t.Identity != nil {
if err := t.Identity.Validate(); err != nil {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Identity %q is invalid: %w", t.Identity.Name, err))
}
}
// Validate Identities
for _, wid := range t.Identities {
// Task.Canonicalize should move the default identity out of the Identities
// slice, so if one is found that means it is a duplicate.
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 {View on GitHub (pinned to 482b49bf1a)
Solutions
- Read the wrapped %w error after 'is invalid:' for the exact field problem
- Fix the identity block per error, e.g. use a valid Go duration for ttl ("1h", "30m")
- Run `nomad job validate job.hcl` locally to iterate on identity validation before submitting
Example fix
// before
identity {
env = true
ttl = "five minutes"
}
// after
identity {
env = true
ttl = "5m"
} Defensive patterns
Strategy: validation
Validate before calling
if t.Identity != nil {
if err := t.Identity.Validate(); err != nil {
return fmt.Errorf("default identity bad: %w", err)
}
} Try / catch
if err := job.Validate(); err != nil {
var mErr *structs.MultiError
if errors.As(err, &mErr) { /* inspect wrapped identity errors */ }
} Prevention
- Use valid Go duration strings for ttl (e.g. "5m", "1h")
- Keep identity options (env/file/aud) consistent with cluster Nomad version
- Run `nomad job validate` before submit to surface identity errors early
When it happens
Trigger: identity { } block in a task whose Validate fails, e.g. identity with an invalid ttl, negative expiration, or file/cloud-platform settings that don't parse; the wrapped error names the identity and the underlying reason.
Common situations: Misconfigured workload identity TTLs (ttl = "five minutes" instead of "5m"); env claiming identity blocks combined with file ones incorrectly; version drift where a new identity option isn't supported by the cluster.
Related errors
- no identities to sign
- no identities requested
- Service identity must provide at least one target aud value
- Duplicate default identities found
- must not be nil
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/2c5d33a8473306f3.
Report an issue: GitHub.