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)
		return

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix the (jobID, allocID) pair so they match — derive the job ID from the alloc: `nomad alloc status <alloc-id>` shows Job ID.
  2. Omit JobID in the exec request; the API does not require it when an alloc ID is given.
  3. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/1ae304890f546753. Report an issue: GitHub.