{"record":{"id":"b896e82d963b713d","repo":"zeroclaw-labs/zeroclaw","slug":"heartbeat-agent-agent-alias-is-not-configu","errorCode":null,"errorMessage":"[heartbeat] agent = {agent_alias:?} is not configured ([agents.{agent_alias}] missing)","messagePattern":"\\[heartbeat\\] agent = (.+?) is not configured \\(\\[agents\\.(.+?)\\] missing\\)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/daemon/mod.rs","lineNumber":1251,"sourceCode":"\n            crate::health::bump_component_restart(name);\n            crate::util::release_freed_heap();\n            tokio::time::sleep(Duration::from_secs(backoff)).await;\n            // Double backoff AFTER sleeping so first error uses initial_backoff\n            backoff = backoff.saturating_mul(2).min(max_backoff);\n        }\n    })\n}\n\nfn resolve_heartbeat_workspace_dir(config: &Config) -> Result<(String, PathBuf)> {\n    let agent_alias = config.heartbeat.agent.trim().to_string();\n    if agent_alias.is_empty() {\n        anyhow::bail!(\n            \"heartbeat worker requires `[heartbeat] agent = \\\"<alias>\\\"` naming a configured agent\"\n        );\n    }\n    if config.agent(&agent_alias).is_none() {\n        anyhow::bail!(\n            \"[heartbeat] agent = {agent_alias:?} is not configured ([agents.{agent_alias}] missing)\"\n        );\n    }\n    let workspace_dir = config.agent_workspace_dir(&agent_alias);\n    Ok((agent_alias, workspace_dir))\n}\n\n/// Test-only hook for [`connect_heartbeat_mcp_registry`]. The daemon\n/// heartbeat worker builds an `Arc<McpRegistry>` once at worker start\n/// and shares it across every tick so that stdio MCP children live\n/// for the daemon's lifetime. Tests inject a hook here to\n/// count invocations and assert the registry is constructed at most\n/// once for N simulated ticks.\n///\n/// Hooks receive the resolved agent alias and the pre-computed list of\n/// MCP server configs granted to that agent by `mcp_bundles`. They\n/// MUST return an `Arc<McpRegistry>` whose inner server lifetime\n/// outlives the simulated ticks (returning a fresh registry per call","sourceCodeStart":1233,"sourceCodeEnd":1269,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/daemon/mod.rs#L1233-L1269","documentation":"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.","triggerScenarios":"[heartbeat] agent = \"assistant\" while config only defines [agents.main]; the [agents.*] table was renamed without updating heartbeat; case mismatch such as \"Main\".","commonSituations":"Renaming agents during a reorganization and forgetting the heartbeat reference; duplicating config across environments where the agent alias differs.","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"],"exampleFix":"# before\n[heartbeat]\nenabled = true\nagent = \"assist\"\n\n[agents.main]\nmodel = \"...\"\n\n# after\n[heartbeat]\nenabled = true\nagent = \"main\"\n\n[agents.main]\nmodel = \"...\"","handlingStrategy":"validation","validationCode":"let alias = config.heartbeat.agent.trim();\nif config.heartbeat.enabled && config.agent(alias).is_none() {\n    anyhow::bail!(\"[heartbeat] agent = {alias:?} has no matching [agents.{alias}] table\");\n}","typeGuard":"fn heartbeat_agent_resolves(config: &zeroclaw_config::schema::Config) -> bool {\n    let alias = config.heartbeat.agent.trim();\n    !config.heartbeat.enabled || config.agent(alias).is_some()\n}","tryCatchPattern":"if let Err(err) = run_heartbeat_worker(config.clone()).await {\n    if err.to_string().contains(\"is not configured\") {\n        eprintln!(\"config error: [heartbeat] agent alias does not match any [agents.<alias>] key\");\n    }\n    return Err(err);\n}","preventionTips":["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"],"tags":["heartbeat","agents","config-reference"],"backgroundTag":"unresolved-config-reference","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}