{"record":{"id":"27782a96c2596c1a","repo":"alibaba/open-code-review","slug":"resolve-home-dir-w-27782a","errorCode":null,"errorMessage":"resolve home dir: %w","messagePattern":"resolve home dir: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/persist.go","lineNumber":106,"sourceCode":"\t// Replace separators with -\n\tp = strings.ReplaceAll(p, \"/\", \"-\")\n\tp = strings.ReplaceAll(p, \"\\\\\", \"-\")\n\n\t// Replace colons (from Windows drive letters)\n\tvol = strings.ReplaceAll(vol, \":\", \"_\")\n\n\t// Handle edge case where path was only separators or volume name\n\tresult := vol + p\n\tif result == \"\" {\n\t\treturn \"empty\"\n\t}\n\treturn result\n}\n\nfunc (jw *jsonlWriter) open() error {\n\thome, err := os.UserHomeDir()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"resolve home dir: %w\", err)\n\t}\n\n\tsessionDir := filepath.Join(home, \".opencodereview\", sessionSubDir, encodeRepoPath(jw.repoDir))\n\tif err := os.MkdirAll(sessionDir, 0700); err != nil {\n\t\treturn fmt.Errorf(\"create session dir: %w\", err)\n\t}\n\n\tfilename := filepath.Join(sessionDir, jw.sessionID+\".jsonl\")\n\tf, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"open session file: %w\", err)\n\t}\n\n\tjw.file = f\n\tjw.writer = bufio.NewWriter(f)\n\treturn nil\n}\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/persist.go#L88-L124","documentation":"This error wraps os.UserHomeDir() failures that occur when the JSONL session writer opens its session file. The library stores review sessions under ~/.opencodereview/<sessions>/<encoded-repo>, so it must resolve the user's home directory first. If that resolution fails, no session file can be created and open() aborts with this wrapped error.","triggerScenarios":"newJSONLWriter -> open() calls os.UserHomeDir() and it returns an error: $HOME is unset in the environment and no passwd entry exists for the current user (typical in cron jobs, Docker containers, or bare CI runners running as a non-login user).","commonSituations":"Running `ocr` inside a Docker container without HOME set; systemd services with a minimal Environment=; CI jobs executing as a uid with no home directory; Go cross-runtime environments where user.Current() cannot read /etc/passwd.","solutions":["Set the HOME environment variable to a writable directory (e.g. export HOME=/root or HOME=/tmp) before invoking the tool","Run the process as a user that exists in /etc/passwd with a valid home directory","If in Docker, add ENV HOME=/root to the image or pass -e HOME=... at runtime","Verify with `go env` or a quick `os.UserHomeDir()` test that home resolution succeeds in the target environment"],"exampleFix":"// before (failing shell)\ncron: ocr review ...\n// after\n HOME=/root ocr review ...  # or set HOME in the crontab/service unit","handlingStrategy":"validation","validationCode":"if os.Getenv(\"HOME\") == \"\" {\n    if _, err := os.UserHomeDir(); err != nil {\n        return fmt.Errorf(\"HOME must be set: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := runOCR(); err != nil {\n    var pe *fs.PathError\n    if strings.Contains(err.Error(), \"resolve home dir\") {\n        log.Fatalf(\"Set HOME to a writable directory: %v\", err)\n    }\n}","preventionTips":["Always export HOME in cron jobs, systemd units, and Docker images","Run services as users with valid passwd entries","Smoke-test home resolution in your CI image before depending on the tool"],"tags":["filesystem","environment","home-directory"],"backgroundTag":"home-dir-not-set","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}