hashicorp/nomad · warning
Duplicate key %q in passed metadata
Error message
Duplicate key %q in passed metadata
What it means
Dispatch metadata (req.Meta) is converted to a map, so duplicate keys cannot be represented; validation iterates the map to assert it is a proper set. In practice this guards against upstream decoders that may surface duplicated keys; identical keys in the metadata map are rejected.
Source
Thrown at nomad/job_endpoint.go:2150
func validateDispatchRequest(req *structs.JobDispatchRequest, job *structs.Job, config *Config) error {
// Check the payload constraint is met
hasInputData := len(req.Payload) != 0
if job.ParameterizedJob.Payload == structs.DispatchPayloadRequired && !hasInputData {
return fmt.Errorf("Payload is not provided but required by parameterized job")
} else if job.ParameterizedJob.Payload == structs.DispatchPayloadForbidden && hasInputData {
return fmt.Errorf("Payload provided but forbidden by parameterized job")
}
// Check the payload doesn't exceed the size limit
if l := len(req.Payload); l > DispatchPayloadSizeLimit {
return fmt.Errorf("Payload exceeds maximum size; %d > %d", l, DispatchPayloadSizeLimit)
}
// Check if the metadata is a set
keys := make(map[string]struct{}, len(req.Meta))
for k := range req.Meta {
if _, ok := keys[k]; ok {
return fmt.Errorf("Duplicate key %q in passed metadata", k)
}
keys[k] = struct{}{}
}
required := set.From(job.ParameterizedJob.MetaRequired)
optional := set.From(job.ParameterizedJob.MetaOptional)
// Check the metadata key constraints are met
unpermitted := make(map[string]struct{})
for k := range req.Meta {
req := required.Contains(k)
opt := optional.Contains(k)
if !req && !opt {
unpermitted[k] = struct{}{}
}
}
if len(unpermitted) != 0 {View on GitHub (pinned to 482b49bf1a)
Solutions
- Deduplicate meta keys before building JobDispatchRequest.Meta
- Ensure a single source of truth for meta (flags should override config, not append)
- Check for merge/annotation code that can inject duplicate keys
Example fix
// before
meta := map[string]string{cfg.Meta}
for k, v := range flagMeta { meta[k] = meta[k] + v } // duplication risk
// after
meta := map[string]string{}
for k, v := range cfg.Meta { meta[k] = v }
for k, v := range flagMeta { meta[k] = v } // flags override, never duplicate Defensive patterns
Strategy: validation
Validate before calling
seen := map[string]struct{}{}
for k := range meta {
if _, dup := seen[k]; dup { return fmt.Errorf("duplicate meta key %q", k) }
seen[k] = struct{}{}
} Prevention
- Build Meta from a single merged map with clear precedence rules
- Avoid concatenative merges that can duplicate keys
- Review middleware that injects default meta keys
When it happens
Trigger: Submitting a JobDispatchRequest whose Meta map contains duplicate keys (possible when request data is merged/decoded from multiple sources before reaching the RPC).
Common situations: Merging meta from config files and CLI flags where the same key appears twice; JSON/HCL decoding merging duplicate keys into conflicting entries; middleware injecting meta that collides with user-provided meta.
Related errors
- Dispatch request included unpermitted metadata keys: %v
- unknown task name %q
- must specify at least one healthy/unhealthy allocation ID
- missing job for registration
- missing job ID for revert
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/d8d00408c7e0db6c.
Report an issue: GitHub.