hashicorp/nomad · error

nil allocation

Error message

nil allocation

What it means

Nomad's client helper `verifiedTasks` validates an allocation and requested task names before performing task-level API operations (e.g. logs/exec/signal). It throws "nil allocation" when the *structs.Allocation passed in is nil, because no validation or task lookup can proceed without one. This is a defensive check in the client layer to fail fast with a clear message instead of panicking on a nil dereference.

Source

Thrown at client/client.go:3060

	cfg := nsd.ServiceRegistrationHandlerCfg{
		Datacenter: c.Datacenter(),
		Enabled:    c.GetConfig().NomadServiceDiscovery,
		NodeID:     c.NodeID(),
		NodeSecret: c.secretNodeID(),
		Region:     c.Region(),
		RPCFn:      c.RPC,
		CheckWatcher: serviceregistration.NewCheckWatcher(
			c.logger, nsd.NewStatusGetter(c.checkStore),
		),
	}
	c.nomadService = nsd.NewServiceRegistrationHandler(c.logger, &cfg)
}

// verifiedTasks asserts each task in taskNames actually exists in the given alloc,
// otherwise an error is returned.
func verifiedTasks(logger hclog.Logger, alloc *structs.Allocation, taskNames []string) ([]string, error) {
	if alloc == nil {
		return nil, fmt.Errorf("nil allocation")
	}

	if len(taskNames) == 0 {
		return nil, fmt.Errorf("missing task names")
	}

	group := alloc.Job.LookupTaskGroup(alloc.TaskGroup)
	if group == nil {
		return nil, fmt.Errorf("group name in allocation is not present in job")
	}

	verifiedTasks := make([]string, 0, len(taskNames))

	// confirm the requested task names actually exist in the allocation
	for _, taskName := range taskNames {
		if !taskIsPresent(taskName, group.Tasks) {
			logger.Error("task not found in the allocation", "task_name", taskName)
			return nil, fmt.Errorf("task %q not found in allocation", taskName)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix the caller so a nil alloc is caught before reaching verifiedTasks — verify the allocation ID exists on this client
  2. Re-fetch the allocation from the server if the client's local copy may have been GC'd
  3. Check the alloc ID in your API request for typos or stale values from a previous deployment

Example fix

// before
alloc := c.getAlloc(allocID)
verified, err := verifiedTasks(logger, alloc, tasks) // panics/errors on nil
// after
alloc := c.getAlloc(allocID)
if alloc == nil {
    return fmt.Errorf("allocation %q not found on client", allocID)
}
verified, err := verifiedTasks(logger, alloc, tasks)
Defensive patterns

Strategy: validation

Validate before calling

if alloc == nil {
    return fmt.Errorf("allocation %q not found: cannot verify tasks", allocID)
}
// then call the client API

Type guard

func allocExists(alloc *structs.Allocation) bool {
    return alloc != nil && alloc.ID != ""
}

Try / catch

verified, err := verifiedTasks(logger, alloc, taskNames)
if err != nil {
    return fmt.Errorf("task verification failed: %w", err)
}

Prevention

When it happens

Trigger: Calling a client API that resolves tasks for an allocation while passing a nil allocation — typically when the caller obtained the allocation via a lookup that returned nil (unknown alloc ID) and did not check it before calling verifiedTasks.

Common situations: Using a stale or mistyped allocation ID that resolves to nil; querying a client node for an allocation it never ran; race conditions where the allocation was removed from the client's local state before the task-listing call.

Related errors


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