{"record":{"id":"9022619a505953ff","repo":"hashicorp/nomad","slug":"missing-job-id-for-deregistering","errorCode":null,"errorMessage":"missing job ID for deregistering","messagePattern":"missing job ID for deregistering","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/job_endpoint.go","lineNumber":809,"sourceCode":"\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\tpermissionsCheck := []string{acl.NamespaceCapabilitySubmitJob, acl.NamespaceCapabilityPurgeJob}\n\tif !args.Purge {\n\t\tpermissionsCheck = append(permissionsCheck, acl.NamespaceCapabilityDeregisterJob)\n\t}\n\n\tif !aclObj.AllowNsOpAnyOf(args.RequestNamespace(), permissionsCheck...) {\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 deregistering\")\n\t}\n\n\t// Lookup the job\n\tsnap, err := j.srv.fsm.State().Snapshot()\n\tif err != nil {\n\t\treturn err\n\t}\n\tws := memdb.NewWatchSet()\n\tjob, err := snap.JobByID(ws, args.RequestNamespace(), args.JobID)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif job == nil {\n\t\treturn nil\n\t}\n\n\tvar eval *structs.Evaluation\n","sourceCodeStart":791,"sourceCodeEnd":827,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint.go#L791-L827","documentation":"The Job.Deregister RPC validates that a JobID is present before looking up the job; an empty ID cannot identify anything to remove, so Nomad rejects the request with this message. It is a pure request-validation failure thrown before any Raft write.","triggerScenarios":"POST /v1/job/<id> with method DELETE where the request body JobID is empty — usually a hand-built JobDeregisterRequest or a wrapper that fails to copy the ID from the URL path.","commonSituations":"Custom API clients building the deregister payload without JobID; shell scripts with an unexpanded variable (empty $JOB_ID); SDK misuse bypassing the Jobs().Deregister convenience method.","solutions":["Set JobID in the JobDeregisterRequest or use client.Jobs().Deregister(id, purge, nil)","Fail fast in scripts if the job ID variable is empty before calling the API","Validate non-empty input at the automation layer before issuing the DELETE"],"exampleFix":"// before\nif os.Getenv(\"JOB\") == \"\" { os.Exit(0) }\nclient.Jobs().Deregister(os.Getenv(\"JOB\"), false, nil)\n// after\njobID := os.Getenv(\"JOB\")\nif jobID == \"\" { return fmt.Errorf(\"JOB must be set\") }\nclient.Jobs().Deregister(jobID, false, nil)","handlingStrategy":"validation","validationCode":"if jobID == \"\" {\n\treturn fmt.Errorf(\"refusing to deregister: empty job ID\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use client.Jobs().Deregister(id, purge, nil)","Check for unexpanded/empty shell variables before API calls","Log the job ID at call sites to catch empty values early"],"tags":["nomad","validation","deregister"],"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"}