sipeed/picoclaw · error

model %q did not resolve to any provider candidates

Error message

model %q did not resolve to any provider candidates

What it means

After successfully constructing a provider for the requested model, SwitchModel calls resolveModelCandidates(cfg, defaultProvider, value, agent.Fallbacks) to build the fallback candidate chain and gets an empty list. Without candidates the agent has no usable model chain to run on, so the switch is aborted before any agent state (Model/Provider/Candidates) mutates.

Source

Thrown at pkg/agent/agent_command.go:313

		}
		rt.GetModelInfo = func() (string, string) {
			return agent.Model, resolvedCandidateProvider(agent.Candidates, cfg.Agents.Defaults.Provider)
		}
		rt.SwitchModel = func(value string) (string, error) {
			value = strings.TrimSpace(value)
			modelCfg, err := resolvedModelConfig(cfg, value, agent.Workspace)
			if err != nil {
				return "", err
			}

			nextProvider, _, err := providers.CreateProviderFromConfig(modelCfg)
			if err != nil {
				return "", fmt.Errorf("failed to initialize model %q: %w", value, err)
			}

			nextCandidates := resolveModelCandidates(cfg, cfg.Agents.Defaults.Provider, value, agent.Fallbacks)
			if len(nextCandidates) == 0 {
				return "", fmt.Errorf("model %q did not resolve to any provider candidates", value)
			}

			oldModel := agent.Model
			oldProvider := agent.Provider
			agent.Model = value
			agent.Provider = nextProvider
			agent.Candidates = nextCandidates
			agent.ThinkingLevel = parseThinkingLevel(modelCfg.ThinkingLevel)
			agent.ThinkingLevelConfigured = isConfiguredThinkingLevel(modelCfg.ThinkingLevel)

			if oldProvider != nil && oldProvider != nextProvider {
				if stateful, ok := oldProvider.(providers.StatefulProvider); ok {
					stateful.Close()
				}
			}
			return oldModel, nil
		}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Check agents.defaults.provider in config matches a provider that serves the requested model
  2. Re-run /model with the fully qualified model identifier used elsewhere in config
  3. Print/inspect resolvedModelConfig and resolveModelCandidates inputs (config excerpts) to see why the chain is empty
  4. Fall back to a known-good model name, then re-add the problematic one step by step

Example fix

# before
agents:
  defaults:
    provider: anthropic
models:
  fast:
    provider: openai   # never reachable as a candidate

# after
agents:
  defaults:
    provider: openai
Defensive patterns

Strategy: validation

Validate before calling

candidates := resolveModelCandidates(cfg, cfg.Agents.Defaults.Provider, value, agent.Fallbacks)
if len(candidates) == 0 {
    // chain empty: fix agents.defaults.provider vs model entry before calling SwitchModel
}

Type guard

func modelHasCandidates(cfg *config.Config, provider, value string, fallbacks []string) bool {
    return len(resolveModelCandidates(cfg, provider, value, fallbacks)) > 0
}

Prevention

When it happens

Trigger: Config defines the model name but no provider mapping resolves it (e.g. provider defaults disagree with the model entry); fallback chain misconfigured such that filtering removes every candidate; referencing a model alias that exists for provider creation but not in the candidate-resolution rules.

Common situations: Hand-edited config where agents.defaults.provider points at a provider that does not offer the requested model; upgrade changed candidate resolution semantics; duplicate model names across providers with ambiguous resolution; empty fallbacks list plus mismatched default provider.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/02ae9049ededae16. Report an issue: GitHub.