hashicorp/nomad · warning

handle cannot be nil

Error message

handle cannot be nil

What it means

RecoverTask guards against a nil TaskHandle argument and returns this error immediately. RecoverTask is used on client restart to reattach to a running task's handle; a nil handle means the caller passed invalid state.

Source

Thrown at drivers/rawexec/driver.go:316

	if d.config.Enabled {
		health = drivers.HealthStateHealthy
		desc = drivers.DriverHealthy
		attrs["driver.raw_exec"] = pstructs.NewBoolAttribute(true)
	} else {
		health = drivers.HealthStateUndetected
		desc = "disabled"
	}

	return &drivers.Fingerprint{
		Attributes:        attrs,
		Health:            health,
		HealthDescription: desc,
	}
}

func (d *Driver) RecoverTask(handle *drivers.TaskHandle) error {
	if handle == nil {
		return fmt.Errorf("handle cannot be nil")
	}

	// If already attached to handle there's nothing to recover.
	if _, ok := d.tasks.Get(handle.Config.ID); ok {
		d.logger.Trace("nothing to recover; task already exists",
			"task_id", handle.Config.ID,
			"task_name", handle.Config.Name,
		)
		return nil
	}

	// Handle doesn't already exist, try to reattach
	var taskState TaskState
	if err := handle.GetDriverState(&taskState); err != nil {
		d.logger.Error("failed to decode task state from handle", "error", err, "task_id", handle.Config.ID)
		return fmt.Errorf("failed to decode task state from handle: %v", err)
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Pass a valid *drivers.TaskHandle restored from the client's task state
  2. Check the client restore code path: a nil handle usually means the task state on disk is missing/corrupt
  3. As a caller, check the error and skip/invalidate the task rather than retrying with nil

Example fix

// before
err := driver.RecoverTask(nil) // handle cannot be nil
// after
handle, ok := restoredHandles[taskID]
if !ok {
    return fmt.Errorf("no restored handle for task %s", taskID)
}
err := driver.RecoverTask(handle)
Defensive patterns

Strategy: type-guard

Validate before calling

if handle == nil {
    return errors.New("refusing to recover: nil task handle")
}

Type guard

func validHandle(h *drivers.TaskHandle) bool { return h != nil && h.Config != nil && h.Config.ID != "" }

Try / catch

if err := drv.RecoverTask(handle); err != nil && err.Error() == "handle cannot be nil" {
    // treat as restore bug; re-create or invalidate the task
}

Prevention

When it happens

Trigger: Calling Driver.RecoverTask(nil) — typically a programming bug in the client's task restore path rather than a runtime condition.

Common situations: Plugin/client restore logic after an agent crash passing an unmarshalled empty handle; custom tooling invoking the driver plugin API directly with missing handle data.

Related errors


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