{"record":{"id":"56aa460938adfd75","repo":"zeroclaw-labs/zeroclaw","slug":"start-channels-requires-at-least-one-enabled-agen","errorCode":null,"errorMessage":"start_channels requires at least one enabled [agents.<alias>] entry","messagePattern":"start_channels requires at least one enabled \\[agents\\.<alias>\\] entry","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/zeroclaw-channels/src/orchestrator/mod.rs","lineNumber":12006,"sourceCode":"            \"Channels supervisor: no model configured. Waiting for reload \\\n             (complete onboarding at /onboard or set \\\n             [providers.models.<type>.<alias>] model = \\\"...\\\" and reload).\"\n        );\n        cancel.cancelled().await;\n        return Ok(());\n    }\n\n    zeroclaw_providers::pricing::spawn_refresher(config_arc.clone());\n\n    let enabled_agents: Vec<String> = {\n        let mut v: Vec<String> = config\n            .agents\n            .iter()\n            .filter(|(_, a)| a.enabled)\n            .map(|(alias, _)| alias.clone())\n            .collect();\n        if v.is_empty() {\n            anyhow::bail!(\"start_channels requires at least one enabled [agents.<alias>] entry\");\n        }\n        v.sort();\n        v\n    };\n\n    let observer: Arc<dyn Observer> =\n        Arc::from(observability::create_observer(&config.observability));\n    let runtime: Arc<dyn platform::RuntimeAdapter> =\n        Arc::from(platform::create_runtime(&config.runtime)?);\n\n    // i18n is process-global; initialize once before the per-agent loop\n    // touches tool descriptions.\n    let i18n_locale = config\n        .locale\n        .as_deref()\n        .filter(|s| !s.is_empty())\n        .map(ToString::to_string)\n        .unwrap_or_else(zeroclaw_runtime::i18n::detect_locale);","sourceCodeStart":11988,"sourceCodeEnd":12024,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/orchestrator/mod.rs#L11988-L12024","documentation":"Raised by start_channels (crates/zeroclaw-channels/src/orchestrator/mod.rs:11969), the channels supervisor entrypoint, when the resolved config contains zero `[agents.<alias>]` entries with enabled = true. The supervisor builds its enabled-agent roster before creating the observer and runtime adapter; an empty roster is fatal because there is nothing to attach channels to. Agent entries default to enabled = true, so this usually means agents were explicitly disabled or the [agents] tables are missing entirely.","triggerScenarios":"Calling start_channels with a config where every [agents.<alias>] has enabled = false, or where no [agents.*] tables exist at all — e.g. a hand-edited config that disabled the default agent, a config generated by tooling that omits agents, or a fresh config that never completed onboarding.","commonSituations":"Operators setting enabled = false on all agents to 'park' the bot; config refactors that dropped the [agents.default] table; multi-agent configs where every alias was disabled for maintenance; automated deployments templating a config without the agents section. Related but distinct: if agents exist but none has a resolvable model provider, start_channels instead logs a WARN and waits for reload rather than bailing.","solutions":["Add or re-enable an agent: [agents.default] with enabled = true (the field defaults to true, so simply having the table without enabled = false is enough)","If the config was hand-trimmed, restore the [agents.<alias>] section from a backup or regenerate it via onboarding","Validate the config before launch by counting enabled agents (see validation below) so startup fails fast with a clearer message","If you intentionally want the daemon idle, note start_channels refuses to run with zero enabled agents — keep at least one enabled or do not start the channels supervisor"],"exampleFix":"# before\n # config.toml\n [agents.default]\n enabled = false        # sole agent disabled -> bail\n\n # after\n [agents.default]\n enabled = true","handlingStrategy":"validation","validationCode":"// fail fast with a clearer message than the supervisor's bail\nlet enabled: Vec<&str> = config\n    .agents\n    .iter()\n    .filter(|(_, a)| a.enabled)\n    .map(|(alias, _)| alias.as_str())\n    .collect();\nif enabled.is_empty() {\n    anyhow::bail!(\n        \"config has no enabled [agents.<alias>] entries (found {} disabled): {}\",\n        config.agents.len(),\n        config.agents.keys().cloned().collect::<Vec<_>>().join(\", \")\n    );\n}","typeGuard":"fn has_enabled_agent(cfg: &zeroclaw_config::schema::Config) -> bool {\n    cfg.agents.values().any(|a| a.enabled)\n}","tryCatchPattern":"if let Err(e) = start_channels(config, store, cancel, sop_engine, sop_audit).await {\n    if e.to_string().contains(\"requires at least one enabled\") {\n        // fatal config error: prompt user to enable an [agents.<alias>] entry; do not retry\n    }\n    return Err(e);\n}","preventionTips":["Agent entries default to enabled = true — only explicit `enabled = false` or missing [agents] tables trigger this","Validate enabled-agent count in a config-lint step before deploying, including after bulk-disabling agents for maintenance","Know the sibling behavior: agents present but no resolvable model provider makes start_channels WARN and wait (onboard/reload), not bail — different remediation"],"tags":["zeroclaw","configuration","startup","agents","supervisor"],"backgroundTag":"config-validation-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}