alibaba/open-code-review · error

resume rejected: provider changed from %q to %q without bein

Error message

resume rejected: provider changed from %q to %q without being asked for; %s to resume across providers on purpose

What it means

ValidateResume guards `ocr review --resume` against silently resuming a session under a different LLM provider than the original run. When the stored manifest's provider differs from the request's provider and the caller did not explicitly pass --provider, resume is rejected so config drift cannot quietly change which model vendor performs the review. Passing --provider explicitly signals the switch was intentional.

Source

Thrown at internal/session/resume_identity.go:61

// every rejection.
//
// Checks run top to bottom and the first mismatch decides. Order matters at
// source_artifact vs rule_config: rule_config_sha256 is a single aggregate over
// the rule-text layers and the file filter and cannot be decomposed, so a filter
// change is reported as the input mismatch it actually caused rather than as an
// unattributable rule change.
func (s *ResumeState) ValidateResume(req ResumeRequest) error {
	if s == nil {
		return nil
	}
	if err := s.validateInputIdentity(req.Identity); err != nil {
		return err
	}

	m := s.Manifest
	providerChanged := m.Execution.Provider != req.Provider
	if providerChanged && !req.ProviderExplicit {
		return fmt.Errorf("resume rejected: provider changed from %q to %q without being asked for; %s to resume across providers on purpose", m.Execution.Provider, req.Provider, explicitFlagHint("--provider", req.Provider))
	}
	// Model is only compared within the same provider: switching provider on
	// purpose necessarily brings that provider's own model with it.
	if !providerChanged && m.Execution.Model != req.Model && !req.ModelExplicit {
		return fmt.Errorf("resume rejected: model changed from %q to %q without being asked for; %s to resume across models on purpose", m.Execution.Model, req.Model, explicitFlagHint("--model", req.Model))
	}
	return nil
}

// validateInputIdentity compares only the input half of the resume contract: the
// parent manifest must be verifiable, and every input field must match. Provider
// and model are deliberately left out: those are command-line intent, not
// something derived from the input.
//
// This runs once, at admission, and is never repeated during the run: the caller
// pins the run to the commit endpoints this comparison was made against (see
// agent.SealedInput), so a second comparison could only ever confirm the first.
func (s *ResumeState) validateInputIdentity(id RunIdentity) error {

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Re-run with --provider <new-provider> to confirm you want to switch providers mid-session
  2. Restore the original provider in config/env so it matches the parent session, then resume
  3. Start a fresh review instead of resuming (as the resumeHint suggests)

Example fix

// before
ocr review --resume abc123            # provider drifted in config
// after
ocr review --resume abc123 --provider anthropic  # explicit switch
Defensive patterns

Strategy: validation

Validate before calling

// Check the stored session's provider before resuming
if sess.Manifest != nil && sess.Manifest.Execution.Provider != requestedProvider && !req.ProviderExplicit {
    fmt.Printf("session %s used provider %q; pass --provider %q to switch deliberately\n",
        sess.SessionID, sess.Manifest.Execution.Provider, requestedProvider)
}

Type guard

func resumeProviderMatches(s *session.State, want string) bool {
    return s != nil && s.Manifest != nil && s.Manifest.Execution.Provider == want
}

Try / catch

if err := ValidateResume(s, req); err != nil {
    if strings.Contains(err.Error(), "provider changed") {
        req.ProviderExplicit = true // or re-run with --provider
        return ValidateResume(s, req)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ValidateResume (via `ocr review --resume <id>`) where s.Manifest.Execution.Provider differs from req.Provider while req.ProviderExplicit is false — e.g. the default provider in config changed since the parent session, or an env var like a provider key switched the effective provider.

Common situations: User upgrades open-code-review or edits config to a new default provider, then resumes an old session; CI environment has a different provider configured than the machine that started the run; user toggles between providers (e.g. openai vs anthropic) between runs.

Related errors


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