{"record":{"id":"e5da8c8e6e2a7cc6","repo":"hashicorp/nomad","slug":"must-call-stoptask-for-the-given-task-before-destr","errorCode":null,"errorMessage":"must call StopTask for the given task before Destroy or set force to true","messagePattern":"must call StopTask for the given task before Destroy or set force to true","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/docker/driver.go","lineNumber":1802,"sourceCode":"\t}\n\n\tdockerClient, err := d.getDockerClient()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tc, err := dockerClient.ContainerInspect(d.ctx, h.containerID, mclient.ContainerInspectOptions{})\n\tif err != nil {\n\t\tif errdefs.IsNotFound(err) {\n\t\t\th.logger.Info(\"container was removed out of band, will proceed with DestroyTask\",\n\t\t\t\t\"error\", err)\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"failed to inspect container state: %v\", err)\n\t\t}\n\t} else {\n\t\tif c.Container.State.Running {\n\t\t\tif !force {\n\t\t\t\treturn fmt.Errorf(\"must call StopTask for the given task before Destroy or set force to true\")\n\t\t\t}\n\t\t\tif _, err := dockerClient.ContainerStop(d.ctx, h.containerID, mclient.ContainerStopOptions{Timeout: new(0)}); err != nil {\n\t\t\t\th.logger.Warn(\"failed to stop container during destroy\", \"error\", err)\n\t\t\t}\n\t\t}\n\n\t\tif h.removeContainerOnExit {\n\t\t\tif _, err := dockerClient.ContainerRemove(d.ctx, h.containerID, mclient.ContainerRemoveOptions{Force: true}); err != nil {\n\t\t\t\th.logger.Error(\"error removing container\", \"error\", err)\n\t\t\t}\n\t\t} else {\n\t\t\th.logger.Debug(\"not removing container due to config\")\n\t\t}\n\t}\n\n\tif err := d.cleanupImage(h); err != nil {\n\t\th.logger.Error(\"failed to cleanup image after destroying container\",\n\t\t\t\"error\", err)","sourceCodeStart":1784,"sourceCodeEnd":1820,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/docker/driver.go#L1784-L1820","documentation":"DestroyTask refuses to remove a container that is still running unless force=true or StopTask was called first. This is a safety check so Nomad never hard-kills a running workload without a prior stop (or explicit force), since the driver tracks the task lifecycle.","triggerScenarios":"Calling driver DestroyTask (or internal destroy APIs) directly on a handle whose container still reports State.Running=true, without having invoked StopTask and without the force flag.","commonSituations":"Custom tooling/plugins driving the driver API directly out of order; scripting against Nomad internals during GC tests; writing driver tests that skip the Stop step.","solutions":["Call StopTask on the task handle before DestroyTask.","Pass force=true to DestroyTask if you intentionally want the running container stopped and removed (the driver will ContainerStop it first).","Fix orchestration code so the standard Stop → Destroy lifecycle is respected."],"exampleFix":"// before\nh.DestroyTask(context.Background(), false) // container still running\n// after\nh.StopTask(context.Background(), time.Second*30)\nh.DestroyTask(context.Background(), false)\n// or: h.DestroyTask(ctx, true) to force-stop","handlingStrategy":"try-catch","validationCode":"// check running state before destroy\ninspected, err := client.ContainerInspect(ctx, containerID, mclient.ContainerInspectOptions{})\nif err == nil && inspected.Container.State.Running {\n    client.ContainerStop(ctx, containerID, mclient.ContainerStopOptions{Timeout: new(uint32)})\n}","typeGuard":null,"tryCatchPattern":"err := h.DestroyTask(ctx, false)\nif err != nil && strings.Contains(err.Error(), \"must call StopTask\") {\n    h.StopTask(ctx, 30*time.Second)\n    err = h.DestroyTask(ctx, false)\n}","preventionTips":["Always follow the driver lifecycle: StartTask → StopTask → DestroyTask","Pass force=true only when intentionally tearing down running containers","In tests/tools, assert the handle was stopped before calling destroy"],"tags":["docker","nomad","lifecycle","destroy-task"],"backgroundTag":"task-lifecycle-order-violation","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"}