zeroclaw-labs/zeroclaw · error · anyhow::Error
[heartbeat] agent = {agent_alias:?} is not configured ([agen
Error message
[heartbeat] agent = {agent_alias:?} is not configured ([agents.{agent_alias}] missing) What it means
resolve_heartbeat_workspace_dir looks up config.agent(&agent_alias) to find the [agents.<alias>] entry and its workspace dir. The alias in [heartbeat] agent must match a configured agent exactly; a typo, a renamed agent table, or a missing agent produces this error at heartbeat worker startup.
Source
Thrown at crates/zeroclaw-runtime/src/daemon/mod.rs:1251
crate::health::bump_component_restart(name);
crate::util::release_freed_heap();
tokio::time::sleep(Duration::from_secs(backoff)).await;
// Double backoff AFTER sleeping so first error uses initial_backoff
backoff = backoff.saturating_mul(2).min(max_backoff);
}
})
}
fn resolve_heartbeat_workspace_dir(config: &Config) -> Result<(String, PathBuf)> {
let agent_alias = config.heartbeat.agent.trim().to_string();
if agent_alias.is_empty() {
anyhow::bail!(
"heartbeat worker requires `[heartbeat] agent = \"<alias>\"` naming a configured agent"
);
}
if config.agent(&agent_alias).is_none() {
anyhow::bail!(
"[heartbeat] agent = {agent_alias:?} is not configured ([agents.{agent_alias}] missing)"
);
}
let workspace_dir = config.agent_workspace_dir(&agent_alias);
Ok((agent_alias, workspace_dir))
}
/// Test-only hook for [`connect_heartbeat_mcp_registry`]. The daemon
/// heartbeat worker builds an `Arc<McpRegistry>` once at worker start
/// and shares it across every tick so that stdio MCP children live
/// for the daemon's lifetime. Tests inject a hook here to
/// count invocations and assert the registry is constructed at most
/// once for N simulated ticks.
///
/// Hooks receive the resolved agent alias and the pre-computed list of
/// MCP server configs granted to that agent by `mcp_bundles`. They
/// MUST return an `Arc<McpRegistry>` whose inner server lifetime
/// outlives the simulated ticks (returning a fresh registry per callView on GitHub (pinned to 88bb9c8533)
Solutions
- Make [heartbeat] agent exactly equal an existing [agents.<alias>] key
- Or add the missing [agents.<alias>] table if that agent was supposed to exist
- Restart the daemon
Example fix
# before [heartbeat] enabled = true agent = "assist" [agents.main] model = "..." # after [heartbeat] enabled = true agent = "main" [agents.main] model = "..."
Defensive patterns
Strategy: validation
Validate before calling
let alias = config.heartbeat.agent.trim();
if config.heartbeat.enabled && config.agent(alias).is_none() {
anyhow::bail!("[heartbeat] agent = {alias:?} has no matching [agents.{alias}] table");
} Type guard
fn heartbeat_agent_resolves(config: &zeroclaw_config::schema::Config) -> bool {
let alias = config.heartbeat.agent.trim();
!config.heartbeat.enabled || config.agent(alias).is_some()
} Try / catch
if let Err(err) = run_heartbeat_worker(config.clone()).await {
if err.to_string().contains("is not configured") {
eprintln!("config error: [heartbeat] agent alias does not match any [agents.<alias>] key");
}
return Err(err);
} Prevention
- Keep agent aliases stable; if you must rename, update every reference in the same commit
- Add a startup smoke test that resolves heartbeat.agent against the agents table before enabling
When it happens
Trigger: [heartbeat] agent = "assistant" while config only defines [agents.main]; the [agents.*] table was renamed without updating heartbeat; case mismatch such as "Main".
Common situations: Renaming agents during a reorganization and forgetting the heartbeat reference; duplicating config across environments where the agent alias differs.
Related errors
- heartbeat worker requires `[heartbeat] agent = "<alias>"` na
- heartbeat.target is set to {channel} but channels.{channel}
- agents.{agent_alias}.model_provider is empty; runtime reload
- start_channels requires at least one enabled [agents.<alias>
- agents.{agent_alias}.model_provider = "{agent_ref}" does not
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/b896e82d963b713d.
Report an issue: GitHub.