hashicorp/nomad · error
job %s does not have allocation %s
Error message
job %s does not have allocation %s
What it means
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.
Source
Thrown at nomad/client_alloc_endpoint.go:570
if args.JobID != "" {
// Verify job exists.
job, err := snap.JobByID(nil, args.Namespace, args.JobID)
if err != nil {
handleStreamResultError(err,
new(int64(http.StatusInternalServerError)), encoder)
return
}
if job == nil {
handleStreamResultError(
fmt.Errorf("job %s not found in namespace %s", args.JobID, args.Namespace),
new(int64(http.StatusNotFound)), encoder)
return
}
// Verify requested allocation belongs to the job.
if args.JobID != alloc.JobID {
handleStreamResultError(
fmt.Errorf("job %s does not have allocation %s", args.JobID, alloc.ID),
new(int64(http.StatusBadRequest)), encoder,
)
}
}
nodeID := alloc.NodeID
// Make sure Node is valid and new enough to support RPC
node, err := snap.NodeByID(nil, nodeID)
if err != nil {
handleStreamResultError(err, new(int64(500)), encoder)
return
}
if node == nil {
err := fmt.Errorf("Unknown node %q", nodeID)
handleStreamResultError(err, new(int64(400)), encoder)
returnView on GitHub (pinned to 482b49bf1a)
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.
Example fix
// before
exec({ allocID: a.ID, jobID: 'other-job' })
// after
exec({ allocID: a.ID, jobID: a.JobID }) // jobID from the same allocation Defensive patterns
Strategy: validation
Validate before calling
const alloc = await nomad.alloc(allocID)
if (jobID && alloc.jobID !== jobID) {
throw new Error(`alloc ${allocID} belongs to ${alloc.jobID}, not ${jobID}`)
}
return exec({ allocID, jobID: alloc.jobID, namespace: alloc.namespace }) Type guard
const belongsToJob = (alloc, jobID) => alloc.jobID === jobID
Try / catch
try { await exec({ allocID, jobID }) }
catch (e) {
if (String(e).includes('does not have allocation')) {
const a = await nomad.alloc(allocID)
return exec({ allocID, jobID: a.jobID }) // correct the pairing and retry once
}
throw e
} Prevention
- 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.
When it happens
Trigger: Calling AllocExec with args.JobID set to job A while args.AllocID belongs to job B.
Common situations: 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.
Related errors
- unknown task name %q
- error cmd must have at least one value
- missing secret ID
- command is not present
- namespace cannot contain template delimiters or parenthesis
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/1ae304890f546753.
Report an issue: GitHub.