hashicorp/nomad · error
must specify at least one healthy/unhealthy allocation ID
Error message
must specify at least one healthy/unhealthy allocation ID
What it means
Deployment.SetAllocHealth requires at least one allocation ID in HealthyAllocationIDs or UnhealthyAllocationIDs. Recording health for zero allocations is meaningless, so the server rejects it after the ID check.
Source
Thrown at nomad/deployment_endpoint.go:422
// deployment.
func (d *Deployment) SetAllocHealth(args *structs.DeploymentAllocHealthRequest, reply *structs.DeploymentUpdateResponse) error {
authErr := d.srv.Authenticate(d.ctx, args)
if done, err := d.srv.forward("Deployment.SetAllocHealth", args, args, reply); done {
return err
}
d.srv.MeasureRPCRate("deployment", structs.RateMetricWrite, args)
if authErr != nil {
return structs.ErrPermissionDenied
}
defer metrics.MeasureSince([]string{"nomad", "deployment", "set_alloc_health"}, time.Now())
// Validate the arguments
if args.DeploymentID == "" {
return fmt.Errorf("missing deployment ID")
}
if len(args.HealthyAllocationIDs)+len(args.UnhealthyAllocationIDs) == 0 {
return fmt.Errorf("must specify at least one healthy/unhealthy allocation ID")
}
// Lookup the deployment
snap, err := d.srv.fsm.State().Snapshot()
if err != nil {
return err
}
ws := memdb.NewWatchSet()
deploy, err := snap.DeploymentByID(ws, args.DeploymentID)
if err != nil {
return err
}
if deploy == nil {
return fmt.Errorf("deployment not found")
}
// Check namespace submit-job permissionsView on GitHub (pinned to 482b49bf1a)
Solutions
- Fetch the deployment's allocations (`nomad deployment status <id>`) and pass at least one alloc ID per the API contract
- Gate the call: skip SetAllocHealth when there are no allocs to mark yet
- If using `nomad deployment promote`/`unblock` instead, note those don't need alloc IDs
Example fix
// before
if len(healthy) == 0 { /* still called anyway */ }
callSetAllocHealth(deployID, healthy, nil)
// after
if len(healthy) == 0 && len(unhealthy) == 0 {
return nil // nothing to mark; wait for allocs
}
callSetAllocHealth(deployID, healthy, unhealthy) Defensive patterns
Strategy: validation
Validate before calling
allocs, _, _ := client.Deployments().Allocations(deployID, nil)
if len(allocs) == 0 { return nil } // nothing to mark yet
req := &api.DeploymentAllocHealthRequest{
DeploymentID: deployID,
HealthyAllocationIDs: healthyIDs(allocs),
UnhealthyAllocationIDs: unhealthyIDs(allocs),
} Type guard
function hasAllocIDs(r) { return (r.HealthyAllocationIDs?.length ?? 0) > 0 || (r.UnhealthyAllocationIDs?.length ?? 0) > 0; } Try / catch
try {
await setAllocHealth(req);
} catch (e) {
if (String(e).includes("must specify at least one")) {
// allocs not placed yet — poll deployment status and retry later
return pollAndRetry(deployID);
}
throw e;
} Prevention
- List the deployment's allocations before marking health; skip if none exist
- Ensure your alloc-selection filter can't produce an empty set silently
- Wait for canary allocs to be placed before evaluating health
When it happens
Trigger: Calling SetAllocHealth with a valid DeploymentID but both alloc ID slices empty — e.g. filtering allocations and matching none, or wiring only healthy IDs when there are none and no unhealthy IDs either.
Common situations: Canary health automation that selects allocs by status/name and gets an empty list (deploy just started, no allocs placed yet); script parsing `nomad job allocs` output incorrectly.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- unknown task name %q
- missing deployment ID
- missing job for registration
- missing job ID for revert
- missing parameterized job ID
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/0a2526e16eb5bcec.
Report an issue: GitHub.