{"record":{"id":"c2770eb1d40c8a4f","repo":"juanfont/headscale","slug":"creating-logs-directory-w","errorCode":null,"errorMessage":"creating logs directory: %w","messagePattern":"creating logs directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/hi/docker.go","lineNumber":62,"sourceCode":"\n\trunID := dockertestutil.GenerateRunID()\n\tcontainerName := \"headscale-test-suite-\" + runID\n\tlogsDir := filepath.Join(config.LogsDir, runID)\n\n\tif config.Verbose {\n\t\tlog.Printf(\"Run ID: %s\", runID)\n\t\tlog.Printf(\"Container name: %s\", containerName)\n\t\tlog.Printf(\"Logs directory: %s\", logsDir)\n\t}\n\n\tabsLogsDir, err := filepath.Abs(logsDir)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"getting absolute path for logs directory: %w\", err)\n\t}\n\n\tconst dirPerm = 0o755\n\tif err := os.MkdirAll(absLogsDir, dirPerm); err != nil { //nolint:noinlineerr\n\t\treturn fmt.Errorf(\"creating logs directory: %w\", err)\n\t}\n\n\tif config.CleanBefore {\n\t\tif config.Verbose {\n\t\t\tlog.Printf(\"Running pre-test cleanup...\")\n\t\t}\n\n\t\terr := cleanupBeforeTest(ctx)\n\t\tif err != nil && config.Verbose {\n\t\t\tlog.Printf(\"Warning: pre-test cleanup failed: %v\", err)\n\t\t}\n\t}\n\n\tgoTestCmd := buildGoTestCommand(config)\n\tif config.Verbose {\n\t\tlog.Printf(\"Command: %s\", strings.Join(goTestCmd, \" \"))\n\t}\n","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/hi/docker.go#L44-L80","documentation":"Returned by runTestContainer when os.MkdirAll(absLogsDir, 0o755) fails while creating control_logs/<runID>. Filesystem causes: a parent directory owned by another user (permission denied), a non-directory file occupying part of the path, or read-only filesystem. Distinct from error 298: here the absolute path resolved fine but creation failed.","triggerScenarios":"control_logs (or a path component) exists as a regular file; the repo is on a read-only mount; earlier runs done as root left root-owned directories; disk quota exhausted.","commonSituations":"Mixing sudo and non-sudo test runs creating root-owned control_logs; CI containers mounting the workspace read-only; a stray file named control_logs; full disks or quotas.","solutions":["Inspect the path: ls -ld control_logs — confirm it is a directory you can write","Fix ownership: sudo chown -R $USER control_logs (common after root runs)","Remove any file occupying the directory name: rm control_logs if it is a regular file","Check disk space and mount options (read-only workspace) in CI"],"exampleFix":"# before: root-owned logs dir from an earlier sudo run\nls -ld control_logs   # drwxr-xr-x root root\ngo run ./cmd/hi run TestACL   # creating logs directory: permission denied\n\n# after\nsudo chown -R \"$USER\" control_logs\ngo run ./cmd/hi run TestACL","handlingStrategy":"validation","validationCode":"// Ensure the logs root is a writable directory before test runs.\nconst perm = 0o755\nif err := os.MkdirAll(\"control_logs\", perm); err != nil {\n\tlog.Fatalf(\"cannot create logs dir: %v\", err)\n}\nif fi, err := os.Stat(\"control_logs\"); err != nil || !fi.IsDir() {\n\tlog.Fatal(\"control_logs exists but is not a directory\")\n}","typeGuard":"func isWritableDir(path string) bool {\n\tfi, err := os.Stat(path)\n\treturn err == nil && fi.IsDir() && fi.Mode().Perm()&0o200 != 0\n}","tryCatchPattern":"Inspect the wrapped error: os.IsPermission → fix ownership/permissions; os.IsExist with a non-directory → remove the blocking file; read-only filesystem → remount or relocate LogsDir.","preventionTips":["Never mix sudo and non-sudo test runs in the same workspace","Add control_logs to .gitignore and pre-create it in setup scripts","On CI, ensure the workspace mount is read-write","Check disk space before large test sessions"],"tags":["filesystem","permissions","logs","integration-tests"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}