{"record":{"id":"fcb595b5ebd10dd3","repo":"alibaba/open-code-review","slug":"resume-session-q-closed-without-a-run-manifest-s","errorCode":null,"errorMessage":"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","messagePattern":"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; (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/resume_identity.go","lineNumber":95,"sourceCode":"// pins the run to the commit endpoints this comparison was made against (see\n// agent.SealedInput), so a second comparison could only ever confirm the first.\nfunc (s *ResumeState) validateInputIdentity(id RunIdentity) error {\n\tif s == nil {\n\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 {","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/resume_identity.go#L77-L113","documentation":"validateInputIdentity rejects resuming a cleanly-closed session that carries no run manifest. Unlike an interrupted session, this one closed with session_end but never recorded one — either it predates the run-manifest feature or its run failed before freezing a manifest — so its input identity cannot be verified against the current request.","triggerScenarios":"ValidateResume on a session where s.Manifest == nil and s.Closed == true — e.g. resuming a session created by an older build without manifest support, or a run that errored before the manifest was written.","commonSituations":"Upgrading open-code-review and trying to resume sessions created by a pre-manifest version; a parent run that failed early (e.g. provider auth error) leaving a closed but manifest-less session.","solutions":["Start a new review instead of resuming the legacy/failed session","Upgrade-check both sides: if the session predates manifests, no resume is possible — re-run the review","Inspect the session store to confirm the manifest is truly absent (not a storage/path issue)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Only attempt resume on sessions that closed with a manifest\nif sess.Closed && sess.Manifest == nil {\n    return fmt.Errorf(\"session %s has no run manifest (legacy or failed run); re-run the review\", sess.SessionID)\n}","typeGuard":"func hasVerifiableManifest(s *session.State) bool {\n    return s != nil && s.Manifest != nil\n}","tryCatchPattern":"if err := ValidateResume(s, req); err != nil {\n    if strings.Contains(err.Error(), \"closed without a run manifest\") {\n        return startNewReview(req) // legacy/failed session cannot be resumed\n    }\n    return err\n}","preventionTips":["Recreate old sessions with the current build before relying on resume","Don't resume sessions whose original run failed early (auth/config errors)","Filter session listings to manifest-bearing sessions when scripting resume"],"tags":["session","resume","manifest","versioning"],"backgroundTag":"resume-unverifiable-session","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}