{"record":{"id":"1ed8180765c713bd","repo":"alibaba/open-code-review","slug":"create-session-writer-w","errorCode":null,"errorMessage":"create session writer: %w","messagePattern":"create session writer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/history.go","lineNumber":175,"sourceCode":"\t\tRepoDir:      repoDir,\n\t\tGitBranch:    gitBranch,\n\t\tModel:        model,\n\t\tReviewMode:   opts.ReviewMode,\n\t\tDiffFrom:     opts.DiffFrom,\n\t\tDiffTo:       opts.DiffTo,\n\t\tDiffCommit:   opts.DiffCommit,\n\t\tScanPaths:    append([]string(nil), opts.ScanPaths...),\n\t\tResumedFrom:  opts.ResumedFrom,\n\t\tStartTime:    time.Now(),\n\t\tFileSessions: make(map[string]*FileSession),\n\t}\n\n\tp, err := newJSONLWriter(sessionID, repoDir, gitBranch, model, opts)\n\tif err != nil {\n\t\t// Do not print here: New runs before JSON output is silenced, so writing a\n\t\t// warning to stdout would corrupt the command's machine-readable output.\n\t\t// Finalize returns this cached delivery error to the command layer.\n\t\tsh.persistInitErr = fmt.Errorf(\"create session writer: %w\", err)\n\t} else {\n\t\tsh.persist = p\n\t\tp.WriteSessionStart(sh.StartTime)\n\t}\n\n\tif opts.Operation != \"\" {\n\t\tsh.manifest = NewManifestBuilder(sessionID, opts.Operation)\n\t}\n\n\treturn sh\n}\n\n// Manifest returns the run's coverage builder, or nil for legacy/scan sessions\n// that did not opt in via SessionOptions.Operation. Callers must be nil-safe.\nfunc (sh *SessionHistory) Manifest() *ManifestBuilder {\n\tif sh == nil {\n\t\treturn nil\n\t}","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/history.go#L157-L193","documentation":"session.New initializes the JSONL session writer (newJSONLWriter). If it cannot create the writer, the error is cached in sh.persistInitErr (not printed, to keep machine-readable stdout clean) wrapped as 'create session writer: ...', and delivered later by Finalize to the command layer. The command still runs; only session persistence fails.","triggerScenarios":"Calling session.New when newJSONLWriter fails — e.g. ~/.opencodereview/sessions cannot be created (HOME unset, permission denied, path is a file) or the session file cannot be opened for writing.","commonSituations":"Read-only home directory, disk full, HOME not set in CI containers, ~/.opencodereview/sessions/<repo> existing as a regular file, SELinux/AppArmor restrictions.","solutions":["Ensure $HOME is set and writable; create ~/.opencodereview with correct permissions.","Free disk space if the disk is full.","Remove/rename any file that occupies the expected session directory path.","Inspect the wrapped cause from Finalize's returned error for the exact OS error."],"exampleFix":"// before\n// HOME unset in CI container, session writer creation fails\n// after (CI setup step)\nexport HOME=/home/runner\nmkdir -p $HOME/.opencodereview","handlingStrategy":"try-catch","validationCode":"home, err := os.UserHomeDir()\nif err != nil {\n    return err\n}\nsdir := filepath.Join(home, \".opencodereview\")\nif err := os.MkdirAll(sdir, 0o755); err != nil {\n    return fmt.Errorf(\"cannot prepare session dir: %w\", err)\n}\nif fi, err := os.Stat(sdir); err == nil && !fi.IsDir() {\n    return fmt.Errorf(\"%s exists but is not a directory\", sdir)\n}","typeGuard":"func hasPersistInitErr(sh *session.History) error {\n    return sh.PersistInitErr() // accessor for the cached writer-creation error, if exported\n}","tryCatchPattern":"err := cmd.Execute()\n// New caches the failure; Finalize delivers it.\nif err != nil && strings.Contains(err.Error(), \"create session writer\") {\n    log.Warnf(\"session persistence disabled: %v\", err) // command output itself may still be usable\n    return nil\n}","preventionTips":["Ensure HOME is set and writable in CI/containers.","Pre-create ~/.opencodereview with correct ownership.","Keep free disk space for session logs.","Never shadow the sessions directory with a regular file."],"tags":["session","filesystem","persistence"],"backgroundTag":"session-persistence-failed","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}