zeroclaw-labs/zeroclaw · error · anyhow::Error

agents.{agent_alias}.model_provider = "{agent_ref}" does not

Error message

agents.{agent_alias}.model_provider = "{agent_ref}" does not resolve to a configured [providers.models.<type>.<alias>] entry

What it means

The same dangling-reference guard as at construction time, enforced again on the non-interactive process_message path (cron, channels, gateway-driven turns): agents.<alias>.model_provider is non-empty but resolved_model_provider_for_agent returns None, so no [providers.models.<type>.<alias>] table matches it. Re-checking at message time catches configs edited after agent construction.

Source

Thrown at crates/zeroclaw-runtime/src/agent/loop_.rs:2908

        // Profile values (when set) override the agent's inline fields.
        // See `Config::resolved_agent_config` for precedence rules.
        let eff_compact_context = agent.resolved.compact_context;
        let eff_max_system_prompt_chars = agent.resolved.max_system_prompt_chars;
        let eff_prompt_injection_mode = agent.resolved.prompt_injection_mode;

        let observer: Arc<dyn Observer> =
            Arc::from(observability::create_observer(&config.observability));
        let runtime: Arc<dyn platform::RuntimeAdapter> =
            Arc::from(platform::create_runtime(&config.runtime)?);
        let security = Arc::new(SecurityPolicy::for_agent(&config, agent_alias)?);
        let (provider_name, provider_alias, agent_model_provider) = match config
            .resolved_model_provider_for_agent(agent_alias)
        {
            Some(resolved) => (resolved.0, resolved.1.to_string(), Some(resolved.2.clone())),
            None => {
                let agent_ref = agent.model_provider.as_str();
                if !agent_ref.is_empty() {
                    anyhow::bail!(
                        "agents.{agent_alias}.model_provider = \"{agent_ref}\" does not resolve to \
                     a configured [providers.models.<type>.<alias>] entry"
                    );
                }
                anyhow::bail!(
                    "agents.{agent_alias}.model_provider is empty \u{2014} set it to a configured \
                 \"<type>.<alias>\" (e.g. \"anthropic.{agent_alias}\")"
                );
            }
        };
        let approval_manager = ApprovalManager::for_non_interactive(&risk_profile);
        let mem: Arc<dyn Memory> = zeroclaw_memory::create_memory_for_agent(
            &config,
            agent_alias,
            agent_model_provider
                .as_ref()
                .and_then(|e| e.api_key.as_deref()),
        )

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Fix the reference to match an existing [providers.models.<type>.<alias>] table (check exact spelling of both segments).
  2. Restore or add the missing provider table.
  3. Reload/restart the runtime after config edits so agents and providers load from one snapshot.
  4. Run the config validation command after every rename.

Example fix

# before
[agents.scheduler]
model_provider = "openai.codex"   # table is [providers.models.openai.main]

# after
[agents.scheduler]
model_provider = "openai.main"
Defensive patterns

Strategy: validation

Validate before calling

// Re-validate before dispatching non-interactive turns
for alias in scheduled_agents {
    anyhow::ensure!(
        config.resolved_model_provider_for_agent(alias).is_some(),
        "agent {alias} has a dangling model_provider — reload config"
    );
}

Try / catch

Catch the error per-message in channel/cron dispatch so one misconfigured agent does not kill the daemon; log agent + reference, skip the turn, and alert — the config must be fixed and reloaded.

Prevention

When it happens

Trigger: A gateway/cron/channel turn referencing an agent whose provider table was renamed or deleted after startup; two config layers where the models table is missing in the layer the runtime actually loaded.

Common situations: Editing config while a daemon is running so agents and provider tables drift out of sync; deploying a partial config; renaming aliases in one file but not the agents file.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/1c8e705c97b94421. Report an issue: GitHub.