sipeed/picoclaw · error

failed to initialize model %q: %w

Error message

failed to initialize model %q: %w

What it means

Raised by the SwitchModel hook: the requested model resolved to a config entry (resolvedModelConfig succeeded), but providers.CreateProviderFromConfig failed to construct a live provider from it. The %w wraps the provider-layer cause: unsupported provider type, missing/invalid API key, malformed base URL, or bad provider-specific settings. The old model/provider are left untouched — switching is atomic on failure.

Source

Thrown at pkg/agent/agent_command.go:308

		return al.reloadFunc()
	}
	if agent != nil {
		if agent.ContextBuilder != nil {
			rt.ListSkillNames = agent.ContextBuilder.ListSkillNames
		}
		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()

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Read the wrapped cause in the message — it names the exact provider failure (auth, unsupported type, URL)
  2. Fix the model's config block: correct provider name, valid API key/env var reference, sane base URL
  3. Verify the key works outside picoclaw (curl the provider endpoint) then retry /model
  4. Stay on the previous model — it remains active since the switch aborted

Example fix

# before
models:
  fast:
    provider: openai      # key never set

# after
export OPENAI_API_KEY=sk-...
# or in config:
models:
  fast:
    provider: openai
    api_key: ${OPENAI_API_KEY}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight the exact same construction the hook performs:
modelCfg, err := resolvedModelConfig(cfg, value, agent.Workspace)
if err != nil { /* invalid name: reject before switching */ }
if _, _, err := providers.CreateProviderFromConfig(modelCfg); err != nil {
    /* provider init fails: show wrapped cause, do not offer switch */
}

Try / catch

_, err := rt.SwitchModel(value)
if err != nil {
    if strings.Contains(err.Error(), "failed to initialize model") {
        // unwrap %w: auth/URL/provider-type errors — fix config/key, retry; current model is unchanged
    }
}

Prevention

When it happens

Trigger: `/model <name>` where the model's provider config lacks an API key, references an unknown provider kind, or carries an invalid endpoint; environment variable for the key unset; provider plugin/SDK initialization error.

Common situations: Adding a new model to config without credentials; expired or revoked API keys; renaming a provider in config after an upgrade; typos in base_url or model fields; air-gapped host failing a provider that phones home at init.

Related errors


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