{"record":{"id":"a06f696947688e8c","repo":"juanfont/headscale","slug":"w-exit-code-d","errorCode":null,"errorMessage":"%w: exit code %d","messagePattern":"%w: exit code (.+?)","errorType":"exception","errorClass":"ErrTestFailed","httpStatus":null,"severity":"error","filePath":"cmd/hi/docker.go","lineNumber":197,"sourceCode":"\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}\n\n\tif config.FailFast {\n\t\tcmd = append(cmd, \"-failfast\")\n\t}","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/hi/docker.go#L179-L215","documentation":"Returned when the test container ran to completion but `go test` inside it exited non-zero. It wraps the `ErrTestFailed` sentinel ('test failed') plus the concrete exit code, so callers can distinguish 'tests actually failed' from infrastructure errors. Exit code 1 means assertion failures; 2 usually means build/setup errors inside the container; 124-style codes can indicate the internal `-timeout` firing.","triggerScenarios":"Any failing assertion or panic in the integration suite; compilation failure of the test binary inside the golang container; `go test -timeout` (config.Timeout) exceeded, which produces a panic dump in the streamed output; Docker exit codes from the container propagate as status.StatusCode.","commonSituations":"Genuine test regressions in hscontrol/mapper/policy; suite timing out on loaded CI machines; environment-dependent tests failing only under Docker (DNS, MTU, address-family differences).","solutions":["Scroll the streamed `go test -v` output above the error — the failing test names and assertion diffs are there.","Inspect `control_logs/<runID>/` for hs-*.stderr.log; per repo docs, flakes are almost always code, not Docker.","If it timed out, raise config.Timeout and re-run to see if it's load-related.","Reproduce a single test: `go run ./cmd/hi run \"TestName\"`.","Try `--postgres` if the failure only appears on one DB backend."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := runDockerTest(ctx, config); err != nil {\n    if errors.Is(err, ErrTestFailed) {\n        // real test failure: read streamed go test -v output and\n        // control_logs/<runID>/hs-*.stderr.log; do NOT retry blindly\n    }\n}","preventionTips":["Treat ErrTestFailed as a code signal, not infra noise — repo docs: flakes are almost always code.","Inspect control_logs artifacts before re-running.","Reproduce single tests with `go run ./cmd/hi run \"TestName\"`.","Test both SQLite and Postgres (--postgres) when a failure is backend-dependent."],"tags":["go-test","assertion-failure","integration-tests","hi-runner"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}