{"record":{"id":"60056de1f05469d3","repo":"juanfont/headscale","slug":"executing-test-w","errorCode":null,"errorMessage":"executing test: %w","messagePattern":"executing test: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/hi/docker.go","lineNumber":193,"sourceCode":"\t\t\tlog.Printf(\"Warning: post-test cleanup failed: %v\", cleanErr)\n\t\t}\n\n\t\t// Clean up artifacts from successful tests to save disk space in CI\n\t\tif exitCode == 0 {\n\t\t\tif config.Verbose {\n\t\t\t\tlog.Printf(\"Test succeeded, cleaning up artifacts to save disk space...\")\n\t\t\t}\n\n\t\t\tcleanErr := cleanupSuccessfulTestArtifacts(logsDir, config.Verbose)\n\n\t\t\tif cleanErr != nil && config.Verbose {\n\t\t\t\tlog.Printf(\"Warning: artifact cleanup failed: %v\", cleanErr)\n\t\t\t}\n\t\t}\n\t}\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"executing test: %w\", err)\n\t}\n\n\tif exitCode != 0 {\n\t\treturn fmt.Errorf(\"%w: exit code %d\", ErrTestFailed, exitCode)\n\t}\n\n\tlog.Printf(\"Test completed successfully!\")\n\n\treturn nil\n}\n\n// buildGoTestCommand constructs the go test command arguments.\nfunc buildGoTestCommand(config *RunConfig) []string {\n\tcmd := []string{\"go\", \"test\", \"./...\"}\n\n\tif config.TestPattern != \"\" {\n\t\tcmd = append(cmd, \"-run\", config.TestPattern)\n\t}","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/hi/docker.go#L175-L211","documentation":"Generic wrapper returned when `streamAndWait` reports an error while streaming output from or waiting on the test container. It covers both the `ContainerLogs` failure path ('getting container logs') and the `ContainerWait` failure path ('waiting for container'), so the wrapped message tells you which half broke. `exitCode` is -1 whenever this fires, meaning the container's real exit status is unknown.","triggerScenarios":"`cli.ContainerLogs` fails to attach (daemon disconnect, container already removed by a concurrent cleanup), or `cli.ContainerWait`'s error channel fires (context cancelled, daemon restart, container killed unexpectedly).","commonSituations":"Docker daemon restarting mid-run; someone runs `docker rm -f` / `hi cleanup` while a test streams; CI machine suspending and dropping the daemon socket; per-command context timeout too short.","solutions":["Check Docker daemon health and recent events: `docker events --since 30m` and daemon logs.","Make sure no concurrent cleanup (`hi clean`, scheduled `docker prune`) runs during the test.","Read the wrapped message: 'getting container logs' vs 'waiting for container' points to attach vs wait APIs.","Re-run the test once the daemon is stable; capture `control_logs/<runID>/` for artifacts if it recurs."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// confirm the daemon is responsive and the container exists before the run\nif err := cli.Ping(ctx); err != nil {\n    return fmt.Errorf(\"docker daemon unreachable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := runDockerTest(ctx, config)\nif err != nil && !errors.Is(err, ErrTestFailed) && !errors.Is(err, ErrMemoryLimitViolations) {\n    // infrastructure-style failure (streaming/waiting): safe to retry once after daemon check\n}","preventionTips":["Avoid running docker prune/cleanup concurrently with test runs.","Use a context timeout sized to config.Timeout plus margin.","Keep the daemon stable (avoid mid-run restarts) in CI."],"tags":["docker","container-wait","streaming","hi-runner","flaky"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}