{"record":{"id":"1d192b9ff09fc600","repo":"alibaba/open-code-review","slug":"resume-session-q-recorded-operation-q-not-q","errorCode":null,"errorMessage":"resume session %q recorded operation %q, not %q; %s","messagePattern":"resume session %q recorded operation %q, not %q; (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/resume_identity.go","lineNumber":99,"sourceCode":"\t\treturn nil\n\t}\n\n\tm := s.Manifest\n\tswitch {\n\tcase m == nil && !s.Closed:\n\t\t// Distinguishing all of these from \"manifest present, zero completed\n\t\t// items\" is the whole point: that one is resumable, none of these are.\n\t\treturn fmt.Errorf(\"resume session %q was interrupted before it closed, so it never recorded a run manifest and its input identity cannot be verified; %s\", s.SessionID, resumeHint)\n\tcase m == nil:\n\t\t// It closed cleanly, so blaming an interruption would send the user\n\t\t// looking for a crash that never happened. A session_end with no manifest\n\t\t// is a session older than run manifests, or a run that failed before\n\t\t// freezing one.\n\t\treturn fmt.Errorf(\"resume session %q closed without a run manifest, so its input identity cannot be verified — it either predates run manifests or failed before recording one; %s\", s.SessionID, resumeHint)\n\tcase m.SchemaVersion != ManifestSchemaVersion:\n\t\treturn fmt.Errorf(\"resume session %q carries manifest schema %q, but this build can only verify %q; %s\", s.SessionID, m.SchemaVersion, ManifestSchemaVersion, resumeHint)\n\tcase m.Operation != OperationReview:\n\t\treturn fmt.Errorf(\"resume session %q recorded operation %q, not %q; %s\", s.SessionID, m.Operation, OperationReview, resumeHint)\n\tcase len(m.Coverage.Selected) == 0:\n\t\t// Without this, an empty parent and an empty child would both hash to the\n\t\t// canonical empty digest, pass every comparison, and produce a run that\n\t\t// reuses nothing and dispatches nothing.\n\t\treturn fmt.Errorf(\"resume session %q selected no input, so it has nothing to resume; %s\", s.SessionID, resumeHint)\n\t}\n\n\tif m.Input.Mode != id.Mode {\n\t\t// Mode feeds item_id derivation, so parent and child items cannot even be\n\t\t// put side by side.\n\t\treturn fmt.Errorf(\"resume rejected: input mode changed from %q to %q; %s\", m.Input.Mode, id.Mode, resumeHint)\n\t}\n\t// Both sides empty means a repository with no remote, which is unchanged.\n\tif m.Repository.IdentitySHA256 != id.RepositorySHA256 {\n\t\treturn fmt.Errorf(\"resume rejected: repository identity changed, so this is not the repository the parent run reviewed; %s\", resumeHint)\n\t}\n\tif m.Input.SourceArtifactSHA256 != id.SourceArtifactSHA256 {\n\t\treturn fmt.Errorf(\"resume rejected: the reviewed input changed since session %q — a ref may now point at a different commit, or the selected file set changed; %s\", s.SessionID, resumeHint)","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/resume_identity.go#L81-L117","documentation":"validateInputIdentity rejects resuming a session whose manifest records an operation other than review (OperationReview). Resume is only defined for review runs; a manifest tagged with a different operation has incompatible semantics and input layout, so verification is refused.","triggerScenarios":"ValidateResume where m.Operation != OperationReview — e.g. pointing --resume at a session created by a non-review command that shares the session store.","commonSituations":"User passes the wrong session ID (a session from another subcommand); a future/other operation type wrote to the same store and the user assumed all sessions are resumable reviews.","solutions":["Verify the session ID refers to a review session; list sessions and pick the correct one","Run the intended operation again instead of resuming a non-review session","Start a new review if the target session was never a review run"],"exampleFix":"// before\nocr review --resume ops-session-id   # wrong session (not a review)\n// after\nocr review --resume review-session-id  # pick a session whose operation is review","handlingStrategy":"validation","validationCode":"// Only resume sessions recorded as review operations\nif sess.Manifest != nil && sess.Manifest.Operation != session.OperationReview {\n    return fmt.Errorf(\"session %s is a %q run, not a review\", sess.SessionID, sess.Manifest.Operation)\n}","typeGuard":"func isReviewSession(m *session.Manifest) bool {\n    return m != nil && m.Operation == session.OperationReview\n}","tryCatchPattern":"if err := ValidateResume(s, req); err != nil {\n    if strings.Contains(err.Error(), \"recorded operation\") {\n        return fmt.Errorf(\"wrong session ID: pick a review session\")\n    }\n    return err\n}","preventionTips":["Copy session IDs from review-run output, not other subcommands","List sessions filtered by operation=review before resuming","Namespace or label session IDs per operation type in scripts"],"tags":["session","resume","operation","cli"],"backgroundTag":"resume-state-mismatch","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}