{"record":{"id":"d8d00408c7e0db6c","repo":"hashicorp/nomad","slug":"duplicate-key-q-in-passed-metadata","errorCode":null,"errorMessage":"Duplicate key %q in passed metadata","messagePattern":"Duplicate key %q in passed metadata","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"nomad/job_endpoint.go","lineNumber":2150,"sourceCode":"func validateDispatchRequest(req *structs.JobDispatchRequest, job *structs.Job, config *Config) error {\n\t// Check the payload constraint is met\n\thasInputData := len(req.Payload) != 0\n\tif job.ParameterizedJob.Payload == structs.DispatchPayloadRequired && !hasInputData {\n\t\treturn fmt.Errorf(\"Payload is not provided but required by parameterized job\")\n\t} else if job.ParameterizedJob.Payload == structs.DispatchPayloadForbidden && hasInputData {\n\t\treturn fmt.Errorf(\"Payload provided but forbidden by parameterized job\")\n\t}\n\n\t// Check the payload doesn't exceed the size limit\n\tif l := len(req.Payload); l > DispatchPayloadSizeLimit {\n\t\treturn fmt.Errorf(\"Payload exceeds maximum size; %d > %d\", l, DispatchPayloadSizeLimit)\n\t}\n\n\t// Check if the metadata is a set\n\tkeys := make(map[string]struct{}, len(req.Meta))\n\tfor k := range req.Meta {\n\t\tif _, ok := keys[k]; ok {\n\t\t\treturn fmt.Errorf(\"Duplicate key %q in passed metadata\", k)\n\t\t}\n\t\tkeys[k] = struct{}{}\n\t}\n\n\trequired := set.From(job.ParameterizedJob.MetaRequired)\n\toptional := set.From(job.ParameterizedJob.MetaOptional)\n\n\t// Check the metadata key constraints are met\n\tunpermitted := make(map[string]struct{})\n\tfor k := range req.Meta {\n\t\treq := required.Contains(k)\n\t\topt := optional.Contains(k)\n\t\tif !req && !opt {\n\t\t\tunpermitted[k] = struct{}{}\n\t\t}\n\t}\n\n\tif len(unpermitted) != 0 {","sourceCodeStart":2132,"sourceCodeEnd":2168,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint.go#L2132-L2168","documentation":"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.","triggerScenarios":"Submitting a JobDispatchRequest whose Meta map contains duplicate keys (possible when request data is merged/decoded from multiple sources before reaching the RPC).","commonSituations":"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.","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"],"exampleFix":"// before\nmeta := map[string]string{cfg.Meta}\nfor k, v := range flagMeta { meta[k] = meta[k] + v } // duplication risk\n// after\nmeta := map[string]string{}\nfor k, v := range cfg.Meta { meta[k] = v }\nfor k, v := range flagMeta { meta[k] = v } // flags override, never duplicate","handlingStrategy":"validation","validationCode":"seen := map[string]struct{}{}\nfor k := range meta {\n    if _, dup := seen[k]; dup { return fmt.Errorf(\"duplicate meta key %q\", k) }\n    seen[k] = struct{}{}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["nomad","api","metadata","validation"],"backgroundTag":"duplicate-key","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}