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 err

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check len(jobs) > 0 before calling BatchDeregister and skip the call otherwise
  2. Fix the filter/selection logic that produced an empty job set
  3. Fall back to individual Job.Deregister calls per job instead of the batch endpoint
  4. 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

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


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