{"record":{"id":"a76df3d7c005e65c","repo":"hashicorp/nomad","slug":"payload-provided-but-forbidden-by-parameterized-jo","errorCode":null,"errorMessage":"Payload provided but forbidden by parameterized job","messagePattern":"Payload provided but forbidden by parameterized job","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/job_endpoint.go","lineNumber":2138,"sourceCode":"\treply.Index = jobCreateIndex\n\n\tif eval != nil {\n\t\treply.EvalID = eval.ID\n\t\treply.EvalCreateIndex = jobCreateIndex\n\t}\n\n\treturn nil\n}\n\n// validateDispatchRequest returns whether the request is valid given the\n// parameterized job.\nfunc 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)","sourceCodeStart":2120,"sourceCodeEnd":2156,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint.go#L2120-L2156","documentation":"The inverse of the required-payload check: if the job declares payload = \"forbidden\" but the dispatch request includes a non-empty payload, Dispatch rejects it because a forbidden-payload job cannot accept input data.","triggerScenarios":"Dispatching a parameterized job with `parameterized { payload = \"forbidden\" }` while sending a non-empty Payload (e.g. piping stdin into `nomad job dispatch`).","commonSituations":"Scripts with unconditional `echo data | nomad job dispatch` reused across jobs; job spec changed to forbidden while callers still send payloads; clients defaulting to attaching a payload.","solutions":["Remove the payload from the dispatch call (no stdin pipe)","If payload is actually needed, change the job spec to `payload = \"required\"` or \"optional\" and resubmit","Audit automation to conditionally send payloads based on the job's declared constraint"],"exampleFix":"// before\necho '{\"x\":1}' | nomad job dispatch batch-process\n// after (job forbids payload)\nnomad job dispatch batch-process","handlingStrategy":"validation","validationCode":"if *job.ParameterizedJob.Payload == \"forbidden\" && len(payload) > 0 {\n    return fmt.Errorf(\"job %s forbids payloads\", jobID)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Don't unconditionally pipe stdin into dispatch commands","Consult ParameterizedJob.Payload in client code before attaching data","Document which jobs forbid payloads in your job catalog"],"tags":["nomad","api","payload","parameterized-job","validation"],"backgroundTag":"invalid-argument-combination","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"}