{"record":{"id":"38d25918e6bae161","repo":"hashicorp/nomad","slug":"cannot-destroy-running-task-38d259","errorCode":null,"errorMessage":"cannot destroy running task","messagePattern":"cannot destroy running task","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/mock/driver.go","lineNumber":576,"sourceCode":"\n\tselect {\n\tcase <-h.waitCh:\n\t\td.logger.Debug(\"not killing task: already exited\", \"task_name\", h.taskConfig.Name)\n\tcase <-time.After(h.killAfter):\n\t\td.logger.Debug(\"killing task due to kill_after\", \"task_name\", h.taskConfig.Name)\n\t\th.kill()\n\t}\n\treturn nil\n}\n\nfunc (d *Driver) DestroyTask(taskID string, force bool) error {\n\thandle, ok := d.tasks.Get(taskID)\n\tif !ok {\n\t\treturn drivers.ErrTaskNotFound\n\t}\n\n\tif handle.IsRunning() && !force {\n\t\treturn fmt.Errorf(\"cannot destroy running task\")\n\t}\n\n\td.tasks.Delete(taskID)\n\treturn nil\n}\n\nfunc (d *Driver) InspectTask(taskID string) (*drivers.TaskStatus, error) {\n\th, ok := d.tasks.Get(taskID)\n\tif !ok {\n\t\treturn nil, drivers.ErrTaskNotFound\n\t}\n\n\treturn h.TaskStatus(), nil\n\n}\n\nfunc (d *Driver) TaskStats(ctx context.Context, taskID string, interval time.Duration) (<-chan *drivers.TaskResourceUsage, error) {\n\tch := make(chan *drivers.TaskResourceUsage)","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/mock/driver.go#L558-L594","documentation":"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.","triggerScenarios":"Calling DestroyTask(ctx, taskID, false) while handle.IsRunning() is true — the task's run goroutine has not finished or been killed.","commonSituations":"Application code calling DestroyTask directly without first StopTask/kill; race between a test teardown and a still-exiting mock task.","solutions":["Stop the task first (StopTask or kill the handle) and wait for it to exit, then call DestroyTask.","Pass force=true to DestroyTask if you intentionally want to discard a running task.","Check handle.IsRunning() before destroying and poll until it returns false."],"exampleFix":"// before\nerr := drv.DestroyTask(ctx, id, false)\n// after\nif h, _ := drv.InspectTask(ctx, id); h.State == drivers.TaskRunning {\n    _ = drv.StopTask(ctx, id, time.Second*30)\n}\nerr := drv.DestroyTask(ctx, id, false)","handlingStrategy":"type-guard","validationCode":"st, err := drv.InspectTask(ctx, taskID)\nif err != nil { return err }\ncanDestroy := st.State != drivers.TaskRunning","typeGuard":"func canDestroy(st *drivers.TaskStatus) bool { return st != nil && st.State != drivers.TaskRunning }","tryCatchPattern":"err := drv.DestroyTask(ctx, id, false)\nif err != nil && strings.Contains(err.Error(), \"cannot destroy running task\") {\n    _ = drv.StopTask(ctx, id, 30*time.Second)\n    err = drv.DestroyTask(ctx, id, false)\n}","preventionTips":["Always StopTask and wait for a non-running state before DestroyTask.","Only pass force=true when you accept losing a running task's data."],"tags":["nomad","mock-driver","task-lifecycle"],"backgroundTag":"task-still-running","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}