alibaba/open-code-review · error

resume rejected: review rule identity changed — either a rul

Error message

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

What it means

Raised when the parent manifest's rule_config_sha256 differs from the freshly computed rule identity of the current invocation. The digest is a single aggregate over all rule text layers (custom, project, global, system) plus the include/exclude file filter, so it can only say 'rules changed', never which rule changed. Resume is rejected because mixing findings computed under two rule sets would produce an incoherent report.

Source

Thrown at internal/session/resume_identity.go:125

	if m.Input.Mode != id.Mode {
		// Mode feeds item_id derivation, so parent and child items cannot even be
		// put side by side.
		return fmt.Errorf("resume rejected: input mode changed from %q to %q; %s", m.Input.Mode, id.Mode, resumeHint)
	}
	// Both sides empty means a repository with no remote, which is unchanged.
	if m.Repository.IdentitySHA256 != id.RepositorySHA256 {
		return fmt.Errorf("resume rejected: repository identity changed, so this is not the repository the parent run reviewed; %s", resumeHint)
	}
	if m.Input.SourceArtifactSHA256 != id.SourceArtifactSHA256 {
		return 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)
	}
	if m.Execution.RuleConfigSHA256 == "" {
		return fmt.Errorf("resume session %q recorded no rule identity, so it cannot be verified against the current rules; %s", s.SessionID, resumeHint)
	}
	if m.Execution.RuleConfigSHA256 != id.RuleConfigSHA256 {
		// The digest is one aggregate, so it can only be attributed to a layer,
		// never to a specific rule or pattern.
		return 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)
	}
	return nil
}

// explicitFlagHint renders the actionable half of a transition rejection. value
// is empty whenever the endpoint has no provider name — one configured straight
// from environment variables has none — and `pass --provider ` is not a command
// anyone can run, so name the flag rather than echoing the empty value.
func explicitFlagHint(flag, value string) string {
	if value == "" {
		return "pass " + flag + " <name> explicitly"
	}
	return "pass " + flag + " " + value
}

// ResumeLineageSchemaVersion versions the resume_lineage event independently of
// the run manifest: lineage records a transition between runs, not a run's
// coverage, so the two evolve separately.

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Revert the rule/config/filter change (checkout the rule files, reinstall the previous CLI version, restore the original include/exclude flags) and retry the resume.
  2. Accept the change and start a new review instead of resuming checkpoints computed under the old rules.
  3. Identify which layer changed by diffing each rule text layer and the file filter against the parent run's values, then decide whether to restore it.

Example fix

// before: rules changed on disk, resume fails
ocr review --resume abc123 --include "**/*.go"
// after: restore the original filter (and rule files) used by the parent run
ocr review --resume abc123 --include "**/*.ts"
Defensive patterns

Strategy: validation

Validate before calling

current := agent.ResolveIdentity(mode, artifact, ruleCfg, repoID)
if current.RuleConfigSHA256 != manifest.Execution.RuleConfigSHA256 {
    // rules changed; prompt the user before resuming
    return errRuleIdentityChanged
}

Type guard

func ruleIdentityMatches(m *Manifest, id RunIdentity) bool { return m != nil && id.RuleConfigSHA256 != "" && m.Execution.RuleConfigSHA256 == id.RuleConfigSHA256 }

Try / catch

if err := state.ValidateResume(req); err != nil {
    if strings.Contains(err.Error(), "rule identity changed") {
        return startNewReview(req) // intentional rule change
    }
    return err
}

Prevention

When it happens

Trigger: Calling ValidateResume after any of: editing a custom/project/global rule text file between the parent run and the resume; upgrading the CLI (system rule layer changed); changing the --include/--exclude file filter; adding or removing rule config files on disk.

Common situations: A teammate committed a new project rule; the user pulled latest and got a newer CLI with updated built-in rules; the resume command line passes different include/exclude globs than the original run.

Related errors


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