hashicorp/nomad · error

failed to decode taskConfig state from handle: %v

Error message

failed to decode taskConfig state from handle: %v

What it means

RecoverTask reads the persisted TaskState (containing the executor's reattach config) from the handle via GetDriverState. If the stored blob cannot be decoded into TaskState, recovery cannot proceed and this wrapped error is returned.

Source

Thrown at drivers/qemu/driver.go:303

func (d *Driver) RecoverTask(handle *drivers.TaskHandle) error {
	if handle == nil {
		return fmt.Errorf("error: 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
	}

	var taskState TaskState
	if err := handle.GetDriverState(&taskState); err != nil {
		d.logger.Error("failed to decode taskConfig state from handle", "error", err, "task_id", handle.Config.ID)
		return fmt.Errorf("failed to decode taskConfig state from handle: %v", err)
	}

	plugRC, err := pstructs.ReattachConfigToGoPlugin(taskState.ReattachConfig)
	if err != nil {
		d.logger.Error("failed to build ReattachConfig from taskConfig state", "error", err, "task_id", handle.Config.ID)
		return fmt.Errorf("failed to build ReattachConfig from taskConfig state: %v", err)
	}

	execImpl, pluginClient, err := executor.ReattachToExecutor(
		plugRC,
		d.logger.With("task_name", handle.Config.Name, "alloc_id", handle.Config.AllocID),
		d.nomadConfig.Topology.Compute(),
	)
	if err != nil {
		d.logger.Error("failed to reattach to executor", "error", err, "task_id", handle.Config.ID)
		return fmt.Errorf("failed to reattach to executor: %v", err)
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. If the underlying task is gone or state is unrecoverable, let the allocation fail and reschedule rather than recovering.
  2. Verify the Nomad client and server are on compatible versions; state format can change across upgrades.
  3. Check the logged inner error for gob/JSON decode details to identify the schema mismatch.
Defensive patterns

Strategy: try-catch

Try / catch

err := d.RecoverTask(handle)
if err != nil && strings.Contains(err.Error(), "failed to decode taskConfig state") {
    // state is unreadable; fall back to rescheduling instead of retrying recovery
    return reschedule(allocID)
}

Prevention

When it happens

Trigger: Calling RecoverTask with a handle whose driver state was written by a different Nomad/driver version, whose state bytes are corrupt, or whose driver state was never set.

Common situations: Nomad client upgraded between agent restarts so the persisted state schema no longer matches; partially written state files after a crash; recovery attempted on a handle created by another driver.

Understand the failure class

Related errors


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