charmbracelet/crush · error

failed to update agent models: %w

Error message

failed to update agent models: %w

What it means

After restoring provider/model overrides from the session's last assistant message, restoreModelFromSession calls AgentCoordinator.UpdateModels to apply them to live agents; failure is wrapped with this message. It means the restored provider/model combination could not be applied — usually because that model no longer resolves against the provider catalog or credentials are missing.

Source

Thrown at internal/app/app.go:487

	}

	if !cfg.IsModelAvailable(lastMsg.Provider, lastMsg.Model) {
		slog.Debug("Skipping model restoration: provider/model not available",
			"provider", lastMsg.Provider,
			"model", lastMsg.Model)
		return nil
	}

	app.config.OverridePreferredModel(config.SelectedModelTypeLarge, config.SelectedModel{
		Provider: lastMsg.Provider,
		Model:    lastMsg.Model,
	})
	if _, ok := cfg.Models[config.SelectedModelTypeSmall]; !ok {
		smallModel := app.GetDefaultSmallModel(lastMsg.Provider)
		app.config.OverridePreferredModel(config.SelectedModelTypeSmall, smallModel)
	}
	if err := app.AgentCoordinator.UpdateModels(ctx); err != nil {
		return fmt.Errorf("failed to update agent models: %w", err)
	}
	slog.Info("Restored model from session",
		"provider", lastMsg.Provider,
		"model", lastMsg.Model)
	return nil
}

// overrideModelsForNonInteractive parses the model strings and temporarily
// overrides the model configurations, then rebuilds the agent.
// Format: "model-name" (searches all providers) or "provider/model-name".
// Model matching is case-insensitive.
// If largeModel is provided but smallModel is not, the small model defaults to
// the provider's default small model.
func (app *App) overrideModelsForNonInteractive(ctx context.Context, largeModel, smallModel string) error {
	providers := app.config.Config().Providers.Copy()

	largeMatches, smallMatches, err := findModels(providers, largeModel, smallModel)
	if err != nil {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Pass an explicit valid --model override to force a currently available model
  2. Reconfigure credentials for the original provider (or accept the new default)
  3. Start a new session instead of --continue if the old model is gone
  4. Update crush so the provider catalog includes the stored model

Example fix

// before
crush run --continue <id> "next step" // old session used removed model
// after
crush run --continue <id> --model anthropic/claude-sonnet-4-5 "next step"
Defensive patterns

Strategy: fallback

Validate before calling

last := getLastAssistantMessage(sessionID) // via crush session data
if last != nil && !modelAvailable(last.Provider, last.Model) {
	// force a known-good model instead of relying on restore
	largeModel = fallbackModel
}

Try / catch

if err := app.RunNonInteractive(ctx, w, prompt, "", "", true, contID, false); err != nil {
	if strings.Contains(err.Error(), "failed to update agent models") {
		// fall back to a current default model
		return app.RunNonInteractive(ctx, w, prompt, fallbackModel, "", true, contID, false)
	}
	return err
}

Prevention

When it happens

Trigger: Continuing a session whose last assistant message used a provider/model that is no longer available (removed from catalog, provider not configured, API key absent) when UpdateModels tries to wire agents.

Common situations: --continue on an old session created with a deprecated model id; API key rotated/removed since the original run; provider catalog changed between versions.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/93c391b940b01c52. Report an issue: GitHub.