charmbracelet/crush · critical

failed to select default models: %w

Error message

failed to select default models: %w

What it means

resolveSelectedModels wraps any failure from cfg.defaultModelSelection with 'failed to select default models: %w'. It is the user-facing wrapper for errors 530-533 (missing default large/small model, no providers, or provider with no models) raised during Load or reloadFromDiskLocked.

Source

Thrown at internal/config/load.go:809

// resolvedModels holds the result of resolving user-configured model
// selections against the provider catalog.
type resolvedModels struct {
	Large         SelectedModel
	Small         SelectedModel
	LargeFallback bool // true if Large was corrected to a default
	SmallFallback bool // true if Small was corrected to a default
}

// resolveSelectedModels validates the user's configured model selections
// against the provider catalog, falling back to defaults when a model ID is
// invalid. It is pure resolution logic: it does not mutate the store or
// touch disk. The caller assigns the results to c.Models and persists any
// fallback corrections as appropriate.
func resolveSelectedModels(cfg *Config, knownProviders []catwalk.Provider) (resolvedModels, error) {
	var result resolvedModels
	defaultLarge, defaultSmall, err := cfg.defaultModelSelection(knownProviders)
	if err != nil {
		return result, fmt.Errorf("failed to select default models: %w", err)
	}
	large, small := defaultLarge, defaultSmall

	largeModelSelected, largeModelConfigured := cfg.Models[SelectedModelTypeLarge]
	if largeModelConfigured {
		if largeModelSelected.Model != "" {
			large.Model = largeModelSelected.Model
		}
		if largeModelSelected.Provider != "" {
			large.Provider = largeModelSelected.Provider
		}
		model := cfg.GetModel(large.Provider, large.Model)
		if model == nil {
			large = defaultLarge
			result.LargeFallback = true
		} else {
			if largeModelSelected.MaxTokens > 0 {
				large.MaxTokens = largeModelSelected.MaxTokens

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Read the wrapped cause after the colon to identify which of the underlying conditions fired
  2. Fix the underlying cause (valid default model IDs, at least one enabled provider with models)
  3. Validate your crush.json/crushrc before startup: providers enabled, default_model_large/default_model_small resolvable
  4. Use crush models to confirm the model IDs you reference exist

Example fix

// before
"anthropic": { "default_model_large": "opus-x" }
// after
"anthropic": { "default_model_large": "claude-sonnet-4-20250514", "models": [{ "id": "claude-sonnet-4-20250514" }] }
Defensive patterns

Strategy: try-catch

Try / catch

models, err := config.Load(ctx, ...)
if err != nil {
  var selErr error
  if strings.Contains(err.Error(), "failed to select default models") {
    fmt.Fprintln(os.Stderr, "model selection failed:", errors.Unwrap(err))
    os.Exit(1)
  }
  return err
}

Prevention

When it happens

Trigger: Load or reloadFromDiskLocked calls resolveSelectedModels and defaultModelSelection returns any error (unresolvable default model IDs, zero enabled providers, first provider has no models).

Common situations: Any of: no providers configured after fresh install; default model IDs stale after a provider catalog update; provider blocks missing models. The wrapped message appears in CLI startup failures.

Related errors


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