Hmbown/CodeWhale · error
Cannot resume agent : status is ( )
Error message
Cannot resume agent {agent_id}: status is {} ({}) What it means
Thrown by `resume_from_checkpoint_with_policy` when the agent exists but its status does not satisfy the requested `ResumePolicy`: `InterruptedOnly` requires status Interrupted, `InterruptedOrCompleted` additionally accepts Completed. The message reports the actual status and the policy description so the caller can pick the right policy.
Solutions
- Read the agent's status first and select the matching policy: InterruptedOnly for Interrupted, InterruptedOrCompleted to also allow Completed.
- If the child is Failed/Cancelled/BudgetExhausted, do not resume — spawn a new child instead.
- If the status changed between check and resume, re-fetch the status and retry with the correct policy.
- Use the policy description in the message to see exactly which statuses the chosen policy accepts.
Example fix
// before
let policy = ResumePolicy::InterruptedOnly;
registry.resume_from_checkpoint_with_policy(&handle, runtime, &agent_id, policy)?;
// after
let policy = match registry.status_of(&agent_id) {
SubAgentStatus::Interrupted(_) => ResumePolicy::InterruptedOnly,
SubAgentStatus::Completed => ResumePolicy::InterruptedOrCompleted,
other => anyhow::bail!("agent is {:?}; cannot resume", other),
};
registry.resume_from_checkpoint_with_policy(&handle, runtime, &agent_id, policy)?; Defensive patterns
Strategy: validation
Validate before calling
let policy = match registry.status_of(agent_id) {
SubAgentStatus::Interrupted(_) => ResumePolicy::InterruptedOnly,
SubAgentStatus::Completed => ResumePolicy::InterruptedOrCompleted,
other => anyhow::bail!("status {:?} does not satisfy any resume policy", other),
}; Type guard
fn policy_allows(policy: &ResumePolicy, status: &SubAgentStatus) -> bool {
match policy {
ResumePolicy::InterruptedOnly => matches!(status, SubAgentStatus::Interrupted(_)),
ResumePolicy::InterruptedOrCompleted => matches!(status, SubAgentStatus::Interrupted(_) | SubAgentStatus::Completed),
}
} Try / catch
match registry.resume_from_checkpoint_with_policy(&handle, runtime, agent_id, policy) {
Err(e) if e.to_string().contains("Cannot resume agent") => {
// re-read status and retry with the matching policy, or spawn a replacement
}
r => r?,
} Prevention
- Derive the ResumePolicy from the child's current status instead of hardcoding it.
- Remember InterruptedOnly rejects Completed children — widen the policy if finished children must resume.
- Re-read the status immediately before resuming to avoid check/act races.
- Treat Failed/Cancelled/BudgetExhausted as never-resumable in policy selection.
When it happens
Trigger: Calling resume with `ResumePolicy::InterruptedOnly` on a Completed (or Running/terminal) child, or with `InterruptedOrCompleted` on a Failed/Cancelled/BudgetExhausted/Running child — the status/policy mismatch fails closed.
Common situations: A resume script uses InterruptedOnly but the child already finished; a caller picks the wrong policy for the situation (trying to resume a cancelled child); the child's status changed from Interrupted to Completed between check and resume.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot continue agent
- Cannot follow up agent
- Agent continuation target is no longer retained
- Agent continuation target is outside the active session
- Agent not found
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1b5f56bfced62653.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:6228
claim,
preserved_profile,
child_route,
) = {
let agent = self
.agents
.get(&agent_id)
.ok_or_else(|| anyhow!("Agent {agent_id} not found"))?;
let resumable = match policy {
ResumePolicy::InterruptedOnly => {
matches!(agent.status, SubAgentStatus::Interrupted(_))
}
ResumePolicy::InterruptedOrCompleted => matches!(
agent.status,
SubAgentStatus::Interrupted(_) | SubAgentStatus::Completed
),
};
if !resumable {
return Err(anyhow!(
"Cannot resume agent {agent_id}: status is {} ({})",
subagent_status_name(&agent.status),
policy.describe()
));
}
let checkpoint = agent
.checkpoint
.as_ref()
.filter(|cp| cp.continuable && !cp.messages.is_empty())
.ok_or_else(|| {
let continuable = agent.checkpoint.as_ref().is_some_and(|cp| cp.continuable);
let messages = agent
.checkpoint
.as_ref()
.map(|cp| cp.messages.len())
.unwrap_or(0);
anyhow!(
"Agent {agent_id} has no continuable checkpoint to resume from (continuable={continuable}, messages={messages})"View on GitHub (pinned to 73e0f67d83)