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
- Fix the reference to match an existing [providers.models.<type>.<alias>] table (check exact spelling of both segments).
- Restore or add the missing provider table.
- Reload/restart the runtime after config edits so agents and providers load from one snapshot.
- 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
- Reload/restart the runtime atomically after config edits so agents and provider tables stay in sync
- Never rename a provider alias without grep-updating all model_provider refs
- Validate the combined config layers actually loaded, not just the file you edited
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
- agents.{agent_alias}.model_provider = "{agent_ref}" does not
- agents.{agent_alias}.model_provider is empty — set it to a c
- agents.{agent_alias}.model_provider resolves to a model_prov
- agents.{agent_alias}.model_provider is empty — set it to a c
- ModelProvider name cannot be empty
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/1c8e705c97b94421.
Report an issue: GitHub.