{"record":{"id":"de08a6fbfb9cbe73","repo":"juanfont/headscale","slug":"listing-containers-w-de08a6","errorCode":null,"errorMessage":"listing containers: %w","messagePattern":"listing containers: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cmd/hi/docker.go","lineNumber":355,"sourceCode":"\tstatusCh, errCh := cli.ContainerWait(ctx, containerID, container.WaitConditionNotRunning)\n\tselect {\n\tcase err := <-errCh:\n\t\tif err != nil {\n\t\t\treturn -1, fmt.Errorf(\"waiting for container: %w\", err)\n\t\t}\n\tcase status := <-statusCh:\n\t\treturn int(status.StatusCode), nil\n\t}\n\n\treturn -1, ErrUnexpectedContainerWait\n}\n\n// waitForContainerFinalization ensures all test containers have properly finished and flushed their output.\nfunc waitForContainerFinalization(ctx context.Context, cli *client.Client, testContainerID string, verbose bool) error {\n\t// First, get all related test containers\n\tcontainers, err := cli.ContainerList(ctx, container.ListOptions{All: true})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"listing containers: %w\", err)\n\t}\n\n\ttestContainers := getCurrentTestContainers(containers, testContainerID, verbose)\n\n\t// Wait for all test containers to reach a final state\n\tmaxWaitTime := 10 * time.Second\n\tcheckInterval := 500 * time.Millisecond\n\ttimeout := time.After(maxWaitTime)\n\n\tticker := time.NewTicker(checkInterval)\n\tdefer ticker.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-timeout:\n\t\t\tif verbose {\n\t\t\t\tlog.Printf(\"Timeout waiting for container finalization, proceeding with artifact extraction\")\n\t\t\t}","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/hi/docker.go#L337-L373","documentation":"Returned by `waitForContainerFinalization` when `cli.ContainerList(All: true)` fails while it polls for all run-related containers to reach a final state (10s budget, 500ms tick). This is a Docker API listing failure, not a per-container problem — the purpose of the function is to ensure test containers flushed output before artifact extraction.","triggerScenarios":"Daemon unreachable or erroring on the list endpoint right after the test container exits; context cancelled before finalization; API version negotiation issues against an old daemon.","commonSituations":"Daemon restarting exactly when the test finishes (heavy CI load); network blip to a remote Docker context; abrupt dockerd OOM-kill during large test runs.","solutions":["Confirm daemon health: `docker ps -a` works after the run.","Re-run the test once the daemon is stable.","If it recurs at test-end on loaded machines, check dockerd memory/OOM events in the journal."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// cheap daemon liveness check before starting the run\nif _, err := cli.ContainerList(ctx, container.ListOptions{Limit: 1}); err != nil {\n    return fmt.Errorf(\"docker list API unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := runDockerTest(ctx, config); err != nil {\n    if strings.Contains(err.Error(), \"listing containers\") && !errors.Is(err, ErrTestFailed) {\n        // post-test finalization failed: test verdict stands; retry only if artifacts needed\n    }\n}","preventionTips":["Keep the daemon healthy through the post-test window.","Don't shut down CI docker services immediately after the test exits.","Treat finalization failures as artifact-risk warnings, not test failures."],"tags":["docker","container-list","finalization","hi-runner"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}