sipeed/picoclaw · error

fallback model %q has no active provider

Error message

fallback model %q has no active provider

What it means

Returned by providerForFallbackCandidate when resolving a fallback candidate: the agent's CandidateProviders registry has no live provider under ModelKey(provider, model), and the active provider is nil, so there is no provider object to send the fallback request through. It means model fallback was configured but no usable provider client exists for it.

Source

Thrown at pkg/agent/pipeline_llm.go:711

	exec.activeModel = resolvedCandidateModel(candidates, rawModel)
	exec.llmModel = exec.activeModel
	exec.activeModelConfig = resolveActiveModelConfig(p.Cfg, ts.agent.Workspace, candidates, rawModel, defaultProvider)
}

func providerForFallbackCandidate(
	agent *AgentInstance,
	activeProvider providers.LLMProvider,
	activeCandidates []providers.FallbackCandidate,
	provider string,
	model string,
) (providers.LLMProvider, error) {
	if agent != nil {
		if cp, ok := agent.CandidateProviders[providers.ModelKey(provider, model)]; ok && cp != nil {
			return cp, nil
		}
	}
	if activeProvider == nil {
		return nil, fmt.Errorf("fallback model %q has no active provider", model)
	}
	return activeProvider, nil
}

func transientLLMRetryReason(err error) (string, bool) {
	if err == nil {
		return "", false
	}

	if failErr := providers.ClassifyError(err, "", ""); failErr != nil {
		switch failErr.Reason {
		case providers.FailoverTimeout:
			if failErr.Status >= 500 {
				return "server_error", true
			}
			return "timeout", true
		case providers.FailoverNetwork:
			return "network", true

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Add complete credentials/config for the fallback's provider so it gets registered in CandidateProviders
  2. Correct the provider/model ids in the fallback configuration to match a configured provider exactly
  3. Remove fallback entries whose providers are intentionally disabled
  4. Ensure the primary provider is constructed before fallback resolution, so activeProvider is non-nil as a last resort

Example fix

# before
providers:
  openai:
    api_key: ${OPENAI_API_KEY}
models:
  fallbacks:
    - provider: anthropic
      model: claude-3-5-sonnet   # no anthropic credentials configured

# after
providers:
  openai:
    api_key: ${OPENAI_API_KEY}
  anthropic:
    api_key: ${ANTHROPIC_API_KEY}
models:
  fallbacks:
    - provider: anthropic
      model: claude-3-5-sonnet
Defensive patterns

Strategy: validation

Validate before calling

func validateFallbackProviders(cfg *config.Config, agent *AgentInstance) error {
    for _, fb := range fallbacks(cfg) {
        key := providers.ModelKey(fb.Provider, fb.Model)
        if _, ok := agent.CandidateProviders[key]; !ok {
            if !providerConfigured(cfg, fb.Provider) {
                return fmt.Errorf("fallback %s/%s has no configured provider (missing credentials?)", fb.Provider, fb.Model)
            }
        }
    }
    return nil
}

Type guard

func isNoActiveProviderError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "has no active provider")
}

Try / catch

prov, err := providerForFallbackCandidate(agent, active, candidates, provider, model)
if err != nil {
    if isNoActiveProviderError(err) {
        // skip this fallback candidate rather than aborting the failover chain
        log.Printf("skipping fallback %s/%s: %v", provider, model, err)
        continue
    }
    return nil, err
}

Prevention

When it happens

Trigger: A fallback model entry whose provider was never constructed — e.g. its API key/provider config missing so no candidate provider got registered in agent.CandidateProviders — combined with an activeProvider of nil (the primary provider itself failed to construct or was never set) at the moment a failover to that model is attempted.

Common situations: Fallback list referencing a provider whose credentials are absent in the environment; provider id typo in fallback config so the key never matches; disabling/removing a provider but leaving it in fallback lists; version changes to ModelKey/provider registration behavior.

Related errors


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