{"record":{"id":"570e5c90ea302b5c","repo":"Hmbown/CodeWhale","slug":"sub-agent-admission-limit-reached-max-admitted","errorCode":null,"errorMessage":"Sub-agent admission limit reached (max_admitted {}, admitted {}, running {}, queued {}). Wait for queued/running agents to finish, cancel unneeded agents, or raise [subagents] max_admitted for this Workflow.","messagePattern":"Sub-agent admission limit reached \\(max_admitted (.+?), admitted (.+?), running (.+?), queued (.+?)\\)\\. Wait for queued/running agents to finish, cancel unneeded agents, or raise \\[subagents\\] max_admitted for this Workflow\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":6792,"sourceCode":"\n    /// Live tasks owned by this session, including queued/stalled tasks until\n    /// their real terminal transition. A heartbeat projection is not proof that\n    /// the task or its completion delivery has settled.\n    pub(crate) fn live_count_for_session(&self, active_session_id: &str) -> usize {\n        self.agents\n            .values()\n            .filter(|agent| {\n                agent.status == SubAgentStatus::Running\n                    && agent.task_handle.is_some()\n                    && self.agent_is_owned_by_session(agent, active_session_id)\n            })\n            .count()\n    }\n\n    fn check_admission_capacity(&self) -> Result<()> {\n        let admitted = self.admitted_count();\n        if admitted >= self.max_admitted_agents {\n            return Err(anyhow!(\n                \"Sub-agent admission limit reached (max_admitted {}, admitted {}, running {}, queued {}). Wait for queued/running agents to finish, cancel unneeded agents, or raise [subagents] max_admitted for this Workflow.\",\n                self.max_admitted_agents,\n                admitted,\n                self.active_count(),\n                self.queued_count()\n            ));\n        }\n        Ok(())\n    }\n\n    fn running_heartbeat_timed_out(&self, agent: &SubAgent) -> bool {\n        agent.status == SubAgentStatus::Running\n            && agent.task_handle.is_some()\n            && agent.last_activity_at.elapsed() >= self.running_heartbeat_timeout\n    }\n\n    pub fn touch(&mut self, agent_id: &str) -> bool {\n        let Some(agent) = self.agents.get_mut(agent_id) else {","sourceCodeStart":6774,"sourceCodeEnd":6810,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/subagent/mod.rs#L6774-L6810","documentation":"The Workflow enforces a cap on how many sub-agents may exist in admitted state (running + queued). `check_admission_capacity` rejects new spawns once `admitted_count()` reaches `max_admitted_agents`, telling the caller to drain or reconfigure rather than silently queueing.","triggerScenarios":"Spawning a new sub-agent (via spawn/admission path) when `admitted >= [subagents] max_admitted`; the error reports max_admitted, admitted, running, and queued counts.","commonSituations":"Fan-out workflows spawning more children than configured; a stuck/leaked running agent blocking admission; too-low `max_admitted` for a parallel map over many items; queued agents never draining because parents wait on them.","solutions":["Wait for queued/running agents to finish, then retry the spawn.","Cancel unneeded agents (agents/cancel or agents/remove) to free admitted slots.","Raise `[subagents] max_admitted` in the Workflow config if the parallelism is intentional.","Check for stuck running agents (no progress) and interrupt/clean them up.","Throttle the fan-out loop to admit in batches."],"exampleFix":"// before\n[subagents]\nmax_admitted = 4\n\n// after\n[subagents]\nmax_admitted = 16  # matches expected fan-out width","handlingStrategy":"try-catch","validationCode":"// gate fan-out before spawning\nwhile admitted_count() >= max_admitted {\n    wait_for_any_agent_to_finish().await;\n}","typeGuard":null,"tryCatchPattern":"match manager.check_admission_capacity() {\n    Err(e) if e.to_string().contains(\"admission limit reached\") => {\n        wait_for_slot().await?;\n        retry_spawn()\n    }\n    other => other,\n}","preventionTips":["Size [subagents] max_admitted to your fan-out width","Admit in bounded batches instead of spawning all children at once","Monitor for stuck running agents that never free slots","Cancel unneeded children promptly"],"tags":["subagent","admission-limit","capacity","config"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}