alibaba/open-code-review · error
resume rejected: model changed from %q to %q without being a
Error message
resume rejected: model changed from %q to %q without being asked for; %s to resume across models on purpose
What it means
ValidateResume rejects resuming a session whose model changed when the provider stayed the same and the caller did not explicitly pass --model. Model identity is only compared within one provider because switching providers intentionally brings that provider's own model. This prevents accidental model drift between the parent run and the resumed run.
Source
Thrown at internal/session/resume_identity.go:66
// 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 {
if s == nil {
return nil
}
m := s.ManifestView on GitHub (pinned to 5cf97d0d15)
Solutions
- Re-run with --model <new-model> to accept the model change explicitly
- Set the model back to the value recorded in the parent session manifest, then resume
- Start a new review instead of resuming
Example fix
// before ocr review --resume abc123 # model default changed since parent run // after ocr review --resume abc123 --model gpt-4o # explicit model override
Defensive patterns
Strategy: validation
Validate before calling
// Verify the model matches the parent manifest before resuming
if sess.Manifest != nil && !providerChanged && sess.Manifest.Execution.Model != requestedModel && !req.ModelExplicit {
fmt.Printf("session %s used model %q; pass --model to switch deliberately\n",
sess.SessionID, sess.Manifest.Execution.Model)
} Type guard
func resumeModelMatches(s *session.State, want string) bool {
return s != nil && s.Manifest != nil && s.Manifest.Execution.Model == want
} Try / catch
if err := ValidateResume(s, req); err != nil {
if strings.Contains(err.Error(), "model changed") {
req.ModelExplicit = true // or re-run with --model
return ValidateResume(s, req)
}
return err
} Prevention
- Pin the model in config; avoid mutable aliases/defaults that drift
- Capture the parent run's provider+model in your script and reuse them on resume
- Treat provider switches as new runs: switch both flags together explicitly
When it happens
Trigger: ValidateResume with providerChanged==false, m.Execution.Model != req.Model, and req.ModelExplicit==false — e.g. the configured model was bumped (gpt-4o to gpt-4.1) or a config default changed between the original run and the resume.
Common situations: User changes their default model in config or environment after starting a review, then resumes; team updated a shared config file pinning a newer model; a model alias resolves differently across environments.
Related errors
- load resume session: %w (run 'ocr session list' to see avail
- %w (run 'ocr session list' to see available sessions)
- resume session %q has no completed scan items (run 'ocr sess
- resume rejected: provider changed from %q to %q without bein
- resume session %q recorded operation %q, not %q; %s
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/d48da0d0370357f3.
Report an issue: GitHub.