{"record":{"id":"10bd7f9b3558588f","repo":"alibaba/open-code-review","slug":"write-session-end-w","errorCode":null,"errorMessage":"write session_end: %w","messagePattern":"write session_end: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/persist.go","lineNumber":405,"sourceCode":"\tjw.lastUUID = uuid\n\n\t// Marshal explicitly (not via writeRecordLocked) so a marshal failure on the\n\t// final record is reported rather than swallowed.\n\tdata, err := json.Marshal(rec)\n\tif err != nil {\n\t\tif jw.writer != nil {\n\t\t\tjw.writer.Flush()\n\t\t}\n\t\tif jw.file != nil {\n\t\t\tjw.file.Close()\n\t\t}\n\t\treturn fmt.Errorf(\"marshal session_end: %w\", err)\n\t}\n\n\tvar writeErr error\n\tif jw.writer != nil {\n\t\tif _, err := jw.writer.Write(data); err != nil {\n\t\t\twriteErr = fmt.Errorf(\"write session_end: %w\", err)\n\t\t} else if err := jw.writer.WriteByte('\\n'); err != nil {\n\t\t\twriteErr = fmt.Errorf(\"write session_end: %w\", err)\n\t\t} else if err := jw.writer.Flush(); err != nil {\n\t\t\twriteErr = fmt.Errorf(\"flush session_end: %w\", err)\n\t\t}\n\t}\n\tif jw.file != nil {\n\t\tif err := jw.file.Close(); err != nil && writeErr == nil {\n\t\t\twriteErr = fmt.Errorf(\"close session file: %w\", err)\n\t\t}\n\t}\n\treturn writeErr\n}\n\nfunc (jw *jsonlWriter) flushAndClose() {\n\tjw.mu.Lock()\n\tdefer jw.mu.Unlock()\n\tif jw.writer != nil {","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/persist.go#L387-L423","documentation":"WriteSessionEnd writes the marshalled session_end JSON line through the bufio.Writer; a failure on the initial Write(data) is reported as 'write session_end'. This is an I/O failure (or a write on an already-broken/closed file), distinct from the later newline-byte and flush failures which reuse the same message.","triggerScenarios":"WriteSessionEnd: jw.writer.Write(data) returns an error — the underlying file descriptor is bad/closed, or an I/O error occurs writing the buffered bytes to the file.","commonSituations":"Writing a session_end after the file was already closed (double finalization); disk became full so buffered writes fail; ENOSPC/EIO on the filesystem hosting $HOME.","solutions":["Check the wrapped error: ENOSPC means free disk space; EBADF means the file was already closed — fix the double-close/double-WriteSessionEnd call path","Ensure WriteSessionEnd is called exactly once per jsonlWriter","Check disk space/quota on $HOME's filesystem","If this recurs on network filesystems, persist sessions on a local disk instead"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure disk has headroom before finalizing\nif fi, err := os.Stat(homeDir); err == nil {\n    _ = fi // or run statfs and check free bytes > record size\n}","typeGuard":null,"tryCatchPattern":"if err := writer.WriteSessionEnd(); err != nil {\n    if strings.Contains(err.Error(), \"write session_end\") {\n        if errors.Is(err, syscall.ENOSPC) {\n            log.Fatal(\"disk full: free space and re-run\")\n        }\n        if errors.Is(err, os.ErrClosed) {\n            log.Fatal(\"session file closed twice: fix finalization path\")\n        }\n    }\n}","preventionTips":["Call WriteSessionEnd exactly once per writer","Ensure adequate disk space/quota on $HOME","Never close the underlying file while the writer is in use"],"tags":["filesystem","io","session-persistence"],"backgroundTag":"disk-full-write-failed","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}