{"record":{"id":"e76cd03d7706c862","repo":"juanfont/headscale","slug":"cleaning-up-containers-for-run-s-w","errorCode":null,"errorMessage":"cleaning up containers for run %s: %w","messagePattern":"cleaning up containers for run (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cmd/hi/cleanup.go","lineNumber":49,"sourceCode":"\n\treturn nil\n}\n\n// cleanupAfterTest removes the test container and all associated integration test containers for the run.\nfunc cleanupAfterTest(ctx context.Context, cli *client.Client, containerID, runID string) error {\n\t// Remove the main test container\n\terr := cli.ContainerRemove(ctx, containerID, container.RemoveOptions{\n\t\tForce: true,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"removing test container: %w\", err)\n\t}\n\n\t// Clean up integration test containers for this run only\n\tif runID != \"\" {\n\t\terr := killTestContainersByRunID(ctx, runID)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"cleaning up containers for run %s: %w\", runID, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// killTestContainers terminates and removes all test containers.\nfunc killTestContainers(ctx context.Context) error {\n\tcli, err := createDockerClient(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"creating Docker client: %w\", err)\n\t}\n\tdefer cli.Close()\n\n\tcontainers, err := cli.ContainerList(ctx, container.ListOptions{\n\t\tAll: true,\n\t})\n\tif err != nil {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/hi/cleanup.go#L31-L67","documentation":"Returned by cleanupAfterTest when killTestContainersByRunID fails. That function lists containers carrying the label hi.run-id=<runID> and force-kills/removes them. The wrapped error is either a Docker client/list failure or, less often, a removal failure, and it names the run ID so you can identify which test run's teardown failed.","triggerScenarios":"Daemon unreachable or user unauthorized at teardown time; containers with the run's label in a state Docker refuses to remove; label-filtered ContainerList failing on very old Docker engines.","commonSituations":"Docker daemon restarted while tests were running; permissions changed mid-session; leftover labeled containers from a crashed run that are half-removed; remote daemon disconnects.","solutions":["Read the wrapped cause after 'cleaning up containers for run <id>:' — it distinguishes list vs remove failures","Manually verify with: docker ps -a --filter label=hi.run-id=<runID>","Run `go run ./cmd/hi kill` to sweep leftovers, then retry","Restart/reconnect Docker if the daemon was down"],"exampleFix":"# inspect leftovers for the failing run\ndocker ps -a --filter \"label=hi.run-id=<runID>\"\n# remove them explicitly\ndocker rm -f $(docker ps -aq --filter \"label=hi.run-id=<runID>\")","handlingStrategy":"retry","validationCode":"# Verify a run's containers before/after teardown\ndocker ps -a --filter \"label=hi.run-id=<runID>\"","typeGuard":null,"tryCatchPattern":"Log the run ID from the message, inspect leftovers via the label filter, remove them explicitly, then retry the hi command if needed.","preventionTips":["Keep the hi.run-id label intact — never rename test containers","Run `hi kill` after crashed runs so labels are cleaned in-band","Monitor daemon stability on CI agents that frequently restart Docker"],"tags":["docker","labels","teardown","integration-tests"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}