{"record":{"id":"1ae304890f546753","repo":"hashicorp/nomad","slug":"job-s-does-not-have-allocation-s-1ae304","errorCode":null,"errorMessage":"job %s does not have allocation %s","messagePattern":"job (.+?) does not have allocation (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"nomad/client_alloc_endpoint.go","lineNumber":570,"sourceCode":"\tif args.JobID != \"\" {\n\t\t// Verify job exists.\n\t\tjob, err := snap.JobByID(nil, args.Namespace, args.JobID)\n\t\tif err != nil {\n\t\t\thandleStreamResultError(err,\n\t\t\t\tnew(int64(http.StatusInternalServerError)), encoder)\n\t\t\treturn\n\t\t}\n\t\tif job == nil {\n\t\t\thandleStreamResultError(\n\t\t\t\tfmt.Errorf(\"job %s not found in namespace %s\", args.JobID, args.Namespace),\n\t\t\t\tnew(int64(http.StatusNotFound)), encoder)\n\t\t\treturn\n\t\t}\n\n\t\t// Verify requested allocation belongs to the job.\n\t\tif args.JobID != alloc.JobID {\n\t\t\thandleStreamResultError(\n\t\t\t\tfmt.Errorf(\"job %s does not have allocation %s\", args.JobID, alloc.ID),\n\t\t\t\tnew(int64(http.StatusBadRequest)), encoder,\n\t\t\t)\n\t\t}\n\t}\n\n\tnodeID := alloc.NodeID\n\n\t// Make sure Node is valid and new enough to support RPC\n\tnode, err := snap.NodeByID(nil, nodeID)\n\tif err != nil {\n\t\thandleStreamResultError(err, new(int64(500)), encoder)\n\t\treturn\n\t}\n\n\tif node == nil {\n\t\terr := fmt.Errorf(\"Unknown node %q\", nodeID)\n\t\thandleStreamResultError(err, new(int64(400)), encoder)\n\t\treturn","sourceCodeStart":552,"sourceCodeEnd":588,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/client_alloc_endpoint.go#L552-L588","documentation":"When a JobID is supplied with an exec request, the handler verifies the target allocation actually belongs to that job. If args.JobID != alloc.JobID, it returns HTTP 400 with this message. It prevents exec'ing into an allocation that is unrelated to the job the client claims.","triggerScenarios":"Calling AllocExec with args.JobID set to job A while args.AllocID belongs to job B.","commonSituations":"Copying an alloc ID from a different job/deployment; automation pairing alloc IDs and job IDs from different sources; cluster with many similarly named jobs where the wrong alloc was selected.","solutions":["Fix the (jobID, allocID) pair so they match — derive the job ID from the alloc: `nomad alloc status <alloc-id>` shows Job ID.","Omit JobID in the exec request; the API does not require it when an alloc ID is given.","In scripts, look up the alloc's job dynamically instead of hardcoding."],"exampleFix":"// before\nexec({ allocID: a.ID, jobID: 'other-job' })\n// after\nexec({ allocID: a.ID, jobID: a.JobID }) // jobID from the same allocation","handlingStrategy":"validation","validationCode":"const alloc = await nomad.alloc(allocID)\nif (jobID && alloc.jobID !== jobID) {\n  throw new Error(`alloc ${allocID} belongs to ${alloc.jobID}, not ${jobID}`)\n}\nreturn exec({ allocID, jobID: alloc.jobID, namespace: alloc.namespace })","typeGuard":"const belongsToJob = (alloc, jobID) => alloc.jobID === jobID","tryCatchPattern":"try { await exec({ allocID, jobID }) }\ncatch (e) {\n  if (String(e).includes('does not have allocation')) {\n    const a = await nomad.alloc(allocID)\n    return exec({ allocID, jobID: a.jobID }) // correct the pairing and retry once\n  }\n  throw e\n}","preventionTips":["Derive jobID from the allocation object rather than separate config.","Never copy alloc IDs across jobs in automation.","Add a pre-flight check comparing alloc.JobID with your expected job."],"tags":["nomad","exec","mismatch","validation"],"backgroundTag":"resource-mismatch","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"}