alibaba/open-code-review · error

parse resume session %q: %w

Error message

parse resume session %q: %w

What it means

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.

Source

Thrown at internal/session/resume.go:153

		if readErr == io.EOF {
			break
		}
		if readErr != nil {
			return nil, fmt.Errorf("read resume session %q: %w", sessionID, readErr)
		}
	}
	if state.SessionID == "" {
		state.SessionID = sessionID
	}
	return state, nil
}

// applyResumeLine folds one record into the index. It reports an unparseable
// line to the caller, which decides whether that is fatal.
func (s *ResumeState) applyResumeLine(line []byte) error {
	var rec resumeRecord
	if err := json.Unmarshal(line, &rec); err != nil {
		return fmt.Errorf("parse resume session %q: %w", s.SessionID, err)
	}

	switch rec.Type {
	case "session_start":
		s.applySessionStart(rec)
	case "review_item_done", "review_item_reused":
		if rec.Fingerprint == "" {
			return nil
		}
		filePath := rec.FilePath
		if filePath == "" {
			filePath = rec.NewPath
		}
		s.Items[rec.Fingerprint] = ResumeItem{
			FilePath:    filePath,
			OldPath:     rec.OldPath,
			NewPath:     rec.NewPath,
			Fingerprint: rec.Fingerprint,

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Inspect the reported line in ~/.opencodereview/.../<sessionID>.jsonl and delete the malformed line (safe: LoadReviewResumeState path tolerates it)
  2. If the torn line is the last one (crash mid-append), truncate the file at the last valid line
  3. Start a fresh session if the file cannot be trusted
  4. Prefer LoadReviewResumeState when losing one checkpoint is acceptable — it skips unparseable lines

Example fix

// before
state, err := session.LoadResumeState(repoDir, sessionID)
// after (drop-one-bad-line semantics)
state, err := session.LoadReviewResumeState(repoDir, sessionID)
Defensive patterns

Strategy: validation

Validate before calling

f, err := os.Open(path)
if err == nil {
	sc := bufio.NewScanner(f)
	for sc.Scan() {
		var probe map[string]json.RawMessage
		if json.Unmarshal(sc.Bytes(), &probe) != nil { /* malformed line found; repair before loading */ }
	}
}

Try / catch

state, err := session.LoadResumeState(repoDir, sessionID)
if err != nil && strings.Contains(err.Error(), "parse resume session") {
	// repair/truncate the JSONL or fall back to LoadReviewResumeState
	return session.LoadReviewResumeState(repoDir, sessionID)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/4938d998e2eaec5c. Report an issue: GitHub.