{"record":{"id":"69d4ba154ae02937","repo":"alibaba/open-code-review","slug":"resume-session-q-carries-manifest-schema-q-but","errorCode":null,"errorMessage":"resume session %q carries manifest schema %q, but this build can only verify %q; %s","messagePattern":"resume session %q carries manifest schema %q, but this build can only verify %q; (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/resume_identity.go","lineNumber":97,"sourceCode":"func (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 {\n\t\treturn fmt.Errorf(\"resume rejected: repository identity changed, so this is not the repository the parent run reviewed; %s\", resumeHint)\n\t}","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/resume_identity.go#L79-L115","documentation":"validateInputIdentity refuses to resume a session whose recorded manifest schema version differs from the version this build can verify (ManifestSchemaVersion). Schema evolution means the stored manifest's fields cannot be trusted or compared safely, so resume is blocked rather than risk a false identity match.","triggerScenarios":"ValidateResume where m.SchemaVersion != ManifestSchemaVersion — typically resuming a session created by an older or newer build of the tool after the manifest schema changed.","commonSituations":"Upgrading or downgrading the binary between the original run and the resume; switching between release channels (stable vs dev) with different manifest schema versions; resuming sessions from an old machine's session store with a new binary.","solutions":["Use the same binary version that created the session to resume it","Start a new review with the current build instead of resuming","Check release notes for manifest schema migrations; migrate or discard old sessions"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify schema compatibility before resuming\nif sess.Manifest != nil && sess.Manifest.SchemaVersion != session.ManifestSchemaVersion {\n    return fmt.Errorf(\"schema %s unsupported by this build (%s)\",\n        sess.Manifest.SchemaVersion, session.ManifestSchemaVersion)\n}","typeGuard":"func schemaSupported(m *session.Manifest) bool {\n    return m != nil && m.SchemaVersion == session.ManifestSchemaVersion\n}","tryCatchPattern":"if err := ValidateResume(s, req); err != nil {\n    if strings.Contains(err.Error(), \"schema\") {\n        return startNewReview(req) // or retry with the original binary version\n    }\n    return err\n}","preventionTips":["Resume with the same binary version that created the session","Read release notes for manifest schema bumps before upgrading mid-review","Archive or discard sessions from incompatible builds instead of resuming"],"tags":["session","resume","schema-version","versioning"],"backgroundTag":"schema-validation-failed","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}