{"record":{"id":"e125ed8ed82072fb","repo":"alibaba/open-code-review","slug":"resume-session-q-recorded-no-rule-identity-so-it","errorCode":null,"errorMessage":"resume session %q recorded no rule identity, so it cannot be verified against the current rules; %s","messagePattern":"resume session %q recorded no rule identity, so it cannot be verified against the current rules; (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/session/resume_identity.go","lineNumber":120,"sourceCode":"\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)\n\t}\n\tif m.Execution.RuleConfigSHA256 == \"\" {\n\t\treturn fmt.Errorf(\"resume session %q recorded no rule identity, so it cannot be verified against the current rules; %s\", s.SessionID, resumeHint)\n\t}\n\tif m.Execution.RuleConfigSHA256 != id.RuleConfigSHA256 {\n\t\t// The digest is one aggregate, so it can only be attributed to a layer,\n\t\t// never to a specific rule or pattern.\n\t\treturn fmt.Errorf(\"resume rejected: review rule identity changed — either a rule text layer (custom, project, global or system) or the include/exclude file filter differs from session %q; %s\", s.SessionID, resumeHint)\n\t}\n\treturn nil\n}\n\n// explicitFlagHint renders the actionable half of a transition rejection. value\n// is empty whenever the endpoint has no provider name — one configured straight\n// from environment variables has none — and `pass --provider ` is not a command\n// anyone can run, so name the flag rather than echoing the empty value.\nfunc explicitFlagHint(flag, value string) string {\n\tif value == \"\" {\n\t\treturn \"pass \" + flag + \" <name> explicitly\"\n\t}\n\treturn \"pass \" + flag + \" \" + value","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/session/resume_identity.go#L102-L138","documentation":"This error is raised during session resume validation when the parent run's manifest exists but its execution.rule_config_sha256 field is empty. The digest is the aggregate identity of the rule configuration (rule text layers plus the include/exclude file filter), and without it the tool cannot prove that the current rules match the ones the parent run used. Rather than silently resuming with possibly different rules, ValidateResume rejects the resume and tells the user to start a new review.","triggerScenarios":"Calling ValidateResume on a session whose manifest was written by a build that did not record Execution.RuleConfigSHA256 (older manifest schema, corrupted/partially written manifest, or a manifest edited to drop the field) — i.e. the manifest is present and closed, but m.Execution.RuleConfigSHA256 == \"\".","commonSituations":"Resuming a session created by an older version of the CLI before rule-identity hashing was introduced; a manifest truncated by a crash mid-write; hand-edited or migrated session files that lost the execution section.","solutions":["Start a fresh review instead of resuming, as the error hint suggests.","Upgrade both the old and new runs to the same CLI version so manifests always include rule_config_sha256, then re-run the parent review once to regenerate a complete manifest.","Inspect the session manifest file to confirm execution.rule_config_sha256 is really empty; if the manifest is corrupted, discard the session."],"exampleFix":"// before: resuming a legacy session\nocr review --resume <session-id>\n// after: regenerate the parent with a current build, then resume\nocr review --resume <new-session-id>","handlingStrategy":"validation","validationCode":"if manifest != nil && manifest.Execution.RuleConfigSHA256 == \"\" {\n    // cannot verify rules; do not attempt resume\n    return fmt.Errorf(\"session %s has no rule identity; start a new review\", sessionID)\n}","typeGuard":"func hasRuleIdentity(m *Manifest) bool { return m != nil && m.Execution.RuleConfigSHA256 != \"\" }","tryCatchPattern":"if err := state.ValidateResume(req); err != nil {\n    var identityErr *IdentityError\n    if errors.As(err, &identityErr) {\n        log.Warn(\"resume rejected; falling back to a fresh review\")\n        return startNewReview(req)\n    }\n    return err\n}","preventionTips":["Always create parent sessions with a build that records rule_config_sha256.","Validate manifest completeness before offering the resume option in tooling.","Never hand-edit session manifests."],"tags":["session","resume","manifest","integrity-check"],"backgroundTag":"resume-identity-mismatch","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}