{"record":{"id":"4938d998e2eaec5c","repo":"alibaba/open-code-review","slug":"parse-resume-session-q-w","errorCode":null,"errorMessage":"parse resume session %q: %w","messagePattern":"parse resume session %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/resume.go","lineNumber":153,"sourceCode":"\t\tif readErr == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif readErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"read resume session %q: %w\", sessionID, readErr)\n\t\t}\n\t}\n\tif state.SessionID == \"\" {\n\t\tstate.SessionID = sessionID\n\t}\n\treturn state, nil\n}\n\n// applyResumeLine folds one record into the index. It reports an unparseable\n// line to the caller, which decides whether that is fatal.\nfunc (s *ResumeState) applyResumeLine(line []byte) error {\n\tvar rec resumeRecord\n\tif err := json.Unmarshal(line, &rec); err != nil {\n\t\treturn fmt.Errorf(\"parse resume session %q: %w\", s.SessionID, err)\n\t}\n\n\tswitch rec.Type {\n\tcase \"session_start\":\n\t\ts.applySessionStart(rec)\n\tcase \"review_item_done\", \"review_item_reused\":\n\t\tif rec.Fingerprint == \"\" {\n\t\t\treturn nil\n\t\t}\n\t\tfilePath := rec.FilePath\n\t\tif filePath == \"\" {\n\t\t\tfilePath = rec.NewPath\n\t\t}\n\t\ts.Items[rec.Fingerprint] = ResumeItem{\n\t\t\tFilePath:    filePath,\n\t\t\tOldPath:     rec.OldPath,\n\t\t\tNewPath:     rec.NewPath,\n\t\t\tFingerprint: rec.Fingerprint,","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/resume.go#L135-L171","documentation":"applyResumeLine returns this when a single JSONL line fails json.Unmarshal into resumeRecord. LoadResumeState treats any unparseable line as fatal (a dropped line could hide a review_item_failed retraction, making coverage unverifiable); LoadReviewResumeState skips such lines instead.","triggerScenarios":"A line in the session .jsonl is not valid JSON — a torn write from a crash mid-append, manual editing, a null byte or binary garbage in the file, or an empty/partial final line.","commonSituations":"Interrupted run left a half-written last line; user hand-edited the session file; another tool truncated or interleaved writes into the JSONL; home dir on a flaky filesystem corrupted the line.","solutions":["Inspect the reported line in ~/.opencodereview/.../<sessionID>.jsonl and delete the malformed line (safe: LoadReviewResumeState path tolerates it)","If the torn line is the last one (crash mid-append), truncate the file at the last valid line","Start a fresh session if the file cannot be trusted","Prefer LoadReviewResumeState when losing one checkpoint is acceptable — it skips unparseable lines"],"exampleFix":"// before\nstate, err := session.LoadResumeState(repoDir, sessionID)\n// after (drop-one-bad-line semantics)\nstate, err := session.LoadReviewResumeState(repoDir, sessionID)","handlingStrategy":"validation","validationCode":"f, err := os.Open(path)\nif err == nil {\n\tsc := bufio.NewScanner(f)\n\tfor sc.Scan() {\n\t\tvar probe map[string]json.RawMessage\n\t\tif json.Unmarshal(sc.Bytes(), &probe) != nil { /* malformed line found; repair before loading */ }\n\t}\n}","typeGuard":null,"tryCatchPattern":"state, err := session.LoadResumeState(repoDir, sessionID)\nif err != nil && strings.Contains(err.Error(), \"parse resume session\") {\n\t// repair/truncate the JSONL or fall back to LoadReviewResumeState\n\treturn session.LoadReviewResumeState(repoDir, sessionID)\n}","preventionTips":["Never hand-edit session JSONL files","If a crash leaves a torn last line, truncate at the last valid JSON line before resuming","Prefer LoadReviewResumeState when a single lost checkpoint is acceptable"],"tags":["go","json","resume","corruption"],"backgroundTag":"json-parse-error","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}