hashicorp/nomad · error

must update at least one allocation

Error message

must update at least one allocation

What it means

UpdateDesiredTransition requires the request to carry at least one allocation ID in args.Allocs; it is a management-only RPC applied via Raft. If the request has an empty Allocs map, the server rejects it with 'must update at least one allocation' instead of committing a no-op Raft entry.

Source

Thrown at nomad/alloc_endpoint.go:368

		return err
	}
	a.srv.MeasureRPCRate("alloc", structs.RateMetricWrite, args)
	if authErr != nil {
		return structs.ErrPermissionDenied
	}

	defer metrics.MeasureSince([]string{"nomad", "alloc", "update_desired_transition"}, time.Now())

	// Check that it is a management token.
	if aclObj, err := a.srv.ResolveACL(args); err != nil {
		return err
	} else if !aclObj.IsManagement() {
		return structs.ErrPermissionDenied
	}

	// Ensure at least a single alloc
	if len(args.Allocs) == 0 {
		return fmt.Errorf("must update at least one allocation")
	}

	// Commit this update via Raft
	_, index, err := a.srv.raftApply(structs.AllocUpdateDesiredTransitionRequestType, args)
	if err != nil {
		a.logger.Error("AllocUpdateDesiredTransitionRequest failed", "error", err)
		return err
	}

	// Setup the response
	reply.Index = index
	return nil
}

// GetServiceRegistrations returns a list of service registrations which belong
// to the passed allocation ID.
func (a *Alloc) GetServiceRegistrations(
	args *structs.AllocServiceRegistrationsRequest,

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Guard the call site: skip the RPC entirely when len(args.Allocs) == 0
  2. Populate args.Allocs with at least one allocation ID and its desired transition before calling
  3. Check the ACL token — only management tokens may call this endpoint at all

Example fix

// before
srv.raftApply(structs.AllocUpdateDesiredTransitionRequestType, args)
// after
if len(args.Allocs) > 0 {
    srv.raftApply(structs.AllocUpdateDesiredTransitionRequestType, args)
}
Defensive patterns

Strategy: validation

Validate before calling

if len(args.Allocs) == 0 {
    return nil // skip UpdateDesiredTransition entirely
}

Try / catch

if err != nil && strings.Contains(err.Error(), "must update at least one allocation") {
    // treat as no-op: nothing to transition
}

Prevention

When it happens

Trigger: Calling the Alloc.UpdateDesiredTransition RPC (internal, management ACL) with an empty Allocs map — e.g. a node drain/reschedule reconciliation pass computing no allocs to transition but still issuing the RPC.

Common situations: Custom tooling or plugins driving node drains; garbage-collection code paths that compute an empty transition set; scripted management calls against the internal API.

Related errors


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