{"record":{"id":"3b9cc3ea47d8e734","repo":"hashicorp/nomad","slug":"missing-job-id-for-revert","errorCode":null,"errorMessage":"missing job ID for revert","messagePattern":"missing job ID for revert","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/job_endpoint.go","lineNumber":564,"sourceCode":"\t}\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"job\", \"revert\"}, time.Now())\n\n\t// Check for submit-job permissions\n\taclObj, err := j.srv.ResolveACL(args)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !aclObj.AllowNsOpAnyOf(args.RequestNamespace(),\n\t\tacl.NamespaceCapabilitySubmitJob,\n\t\tacl.NamespaceCapabilityRevertJob,\n\t) {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\n\t// Validate the arguments\n\tif args.JobID == \"\" {\n\t\treturn fmt.Errorf(\"missing job ID for revert\")\n\t}\n\n\t// Lookup the job by version\n\tsnap, err := j.srv.fsm.State().Snapshot()\n\tif err != nil {\n\t\treturn err\n\t}\n\tws := memdb.NewWatchSet()\n\tcur, err := snap.JobByID(ws, args.RequestNamespace(), args.JobID)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif cur == nil {\n\t\treturn fmt.Errorf(\"job %q not found\", args.JobID)\n\t}\n\tif args.JobVersion == cur.Version {\n\t\treturn fmt.Errorf(\"can't revert to current version\")\n\t}","sourceCodeStart":546,"sourceCodeEnd":582,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint.go#L546-L582","documentation":"Nomad's Job.Revert RPC (nomad/job_endpoint.go:564) requires args.JobID to identify the job whose version is being reverted. When the request omits the job ID, the server cannot look up prior versions and rejects the call before touching state.","triggerScenarios":"Calling Job.Revert (POST /v1/job/<id>/revert or the CLI `nomad job revert`) with an empty JobID — e.g. building the RPC manually, or scripting the HTTP endpoint with an empty/missing path parameter.","commonSituations":"Automation that interpolates an empty job-name variable into the revert URL (/v1/job//revert); wrappers that pass only JobVersion without JobID; jobs deregistered but callers still attempting a revert with a blank identifier.","solutions":["Provide the job ID: POST /v1/job/<job-id>/revert with {\"JobVersion\": N} or run `nomad job revert <job-id> <version>`.","Confirm the job exists with `nomad job status` and use its exact ID (job IDs are case-sensitive and namespace-scoped).","Fix templating/automation so the job ID variable is not empty in the revert call.","If the job was purged, re-register it instead of attempting a revert; revert only works on jobs present in state."],"exampleFix":"// before\ncurl -X POST http://localhost:4646/v1/job//revert -d '{\"JobVersion\": 2}'\n\n// after\ncurl -X POST http://localhost:4646/v1/job/webapp/revert -d '{\"JobVersion\": 2}'","handlingStrategy":"validation","validationCode":"if jobID == \"\" {\n\treturn fmt.Errorf(\"jobID is required for revert; got %q from template\", jobID)\n}\nif _, _, err := client.Jobs().Info(jobID, nil); err != nil {\n\treturn fmt.Errorf(\"cannot revert unknown job %q: %w\", jobID, err)\n}","typeGuard":"func revertArgsValid(jobID string, version uint64) bool {\n\treturn jobID != \"\"\n}","tryCatchPattern":"_, _, err := client.Jobs().Revert(jobID, version, nil, nil)\nif err != nil && strings.Contains(err.Error(), \"missing job ID for revert\") {\n\treturn fmt.Errorf(\"revert called without job ID — check the jobID template variable: %w\", err)\n}","preventionTips":["Fail fast in scripts when $JOB_ID is empty before calling revert.","Always use the CLI (`nomad job revert <id> <version>`) which enforces required args.","Look up the job with Jobs().Info before reverting to confirm it exists.","Never hardcode the revert URL without verifying the interpolated ID."],"tags":["nomad","job-revert","validation","api"],"backgroundTag":"missing-required-argument","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"}