hashicorp/nomad · warning
given no jobs to deregister
Error message
given no jobs to deregister
What it means
Job.BatchDeregister removes multiple jobs in one Raft transaction, but only management-level ACL tokens may use it, and the request must contain at least one job. An empty Jobs slice is rejected because there is nothing to do — Nomad refuses to commit a no-op batch.
Source
Thrown at nomad/job_endpoint.go:916
}
defer metrics.MeasureSince([]string{"nomad", "job", "batch_deregister"}, time.Now())
aclObj, err := j.srv.ResolveACL(args)
if err != nil {
return err
}
// This RPC endpoint is only called from a Nomad server using the leader
// ACL when performing garbage collection, therefore we can get away with a
// simple management check to ensure the caller can trigger this
// functionality as the leader token is always a management token.
if !aclObj.IsManagement() {
return structs.ErrPermissionDenied
}
// Validate the arguments
if len(args.Jobs) == 0 {
return fmt.Errorf("given no jobs to deregister")
}
// Commit this update via Raft
_, index, err := j.srv.raftApply(structs.JobBatchDeregisterRequestType, args)
if err != nil {
j.logger.Error("batch deregister failed", "error", err)
return err
}
reply.Index = index
return nil
}
// Scale is used to modify one of the scaling targets in the job
func (j *Job) Scale(args *structs.JobScaleRequest, reply *structs.JobRegisterResponse) error {
authErr := j.srv.Authenticate(j.ctx, args)
if done, err := j.srv.forward("Job.Scale", args, args, reply); done {
return errView on GitHub (pinned to 482b49bf1a)
Solutions
- Check len(jobs) > 0 before calling BatchDeregister and skip the call otherwise
- Fix the filter/selection logic that produced an empty job set
- Fall back to individual Job.Deregister calls per job instead of the batch endpoint
- If using JSON payloads, ensure the Jobs field is populated in the request body
Example fix
// before
req := &api.JobBatchDeregisterRequest{Jobs: jobs}
client.Jobs().BatchDeregister(req, nil)
// after
if len(jobs) == 0 { return nil }
req := &api.JobBatchDeregisterRequest{Jobs: jobs}
client.Jobs().BatchDeregister(req, nil) Defensive patterns
Strategy: validation
Validate before calling
if len(jobs) == 0 {
return nil // nothing to deregister; skip the batch call
} Prevention
- Short-circuit when the target job set is empty
- Verify the selection filter actually matched jobs
- Prefer per-job Deregister for small sets
When it happens
Trigger: POST /v1/jobs/batch-deregister with a JobBatchDeregisterRequest whose Jobs map is empty or nil, typically built dynamically from a filtered list where every entry was filtered out.
Common situations: Cleanup automation whose job-name filter matched nothing; deserialized JSON missing the 'Jobs' key; scripts that always call the endpoint regardless of collected targets.
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
- must specify at least one namespace
- missing node IDs for client deregistration
- missing secret ID
- namespace cannot contain template delimiters or parenthesis
- wait config is nil or empty
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/e757debf3b5a3a33.
Report an issue: GitHub.