hashicorp/nomad · error

cannot destroy running task

Error message

cannot destroy running task

What it means

Returned by the mock driver's DestroyTask when the task handle is still running and force was not set; the mock driver refuses to destroy a live task unless destruction is forced.

Source

Thrown at drivers/mock/driver.go:576

	select {
	case <-h.waitCh:
		d.logger.Debug("not killing task: already exited", "task_name", h.taskConfig.Name)
	case <-time.After(h.killAfter):
		d.logger.Debug("killing task due to kill_after", "task_name", h.taskConfig.Name)
		h.kill()
	}
	return nil
}

func (d *Driver) DestroyTask(taskID string, force bool) error {
	handle, ok := d.tasks.Get(taskID)
	if !ok {
		return drivers.ErrTaskNotFound
	}

	if handle.IsRunning() && !force {
		return fmt.Errorf("cannot destroy running task")
	}

	d.tasks.Delete(taskID)
	return nil
}

func (d *Driver) InspectTask(taskID string) (*drivers.TaskStatus, error) {
	h, ok := d.tasks.Get(taskID)
	if !ok {
		return nil, drivers.ErrTaskNotFound
	}

	return h.TaskStatus(), nil

}

func (d *Driver) TaskStats(ctx context.Context, taskID string, interval time.Duration) (<-chan *drivers.TaskResourceUsage, error) {
	ch := make(chan *drivers.TaskResourceUsage)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Stop the task first (StopTask or kill the handle) and wait for it to exit, then call DestroyTask.
  2. Pass force=true to DestroyTask if you intentionally want to discard a running task.
  3. Check handle.IsRunning() before destroying and poll until it returns false.

Example fix

// before
err := drv.DestroyTask(ctx, id, false)
// after
if h, _ := drv.InspectTask(ctx, id); h.State == drivers.TaskRunning {
    _ = drv.StopTask(ctx, id, time.Second*30)
}
err := drv.DestroyTask(ctx, id, false)
Defensive patterns

Strategy: type-guard

Validate before calling

st, err := drv.InspectTask(ctx, taskID)
if err != nil { return err }
canDestroy := st.State != drivers.TaskRunning

Type guard

func canDestroy(st *drivers.TaskStatus) bool { return st != nil && st.State != drivers.TaskRunning }

Try / catch

err := drv.DestroyTask(ctx, id, false)
if err != nil && strings.Contains(err.Error(), "cannot destroy running task") {
    _ = drv.StopTask(ctx, id, 30*time.Second)
    err = drv.DestroyTask(ctx, id, false)
}

Prevention

When it happens

Trigger: Calling DestroyTask(ctx, taskID, false) while handle.IsRunning() is true — the task's run goroutine has not finished or been killed.

Common situations: Application code calling DestroyTask directly without first StopTask/kill; race between a test teardown and a still-exiting mock task.

Related errors


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