Hmbown/CodeWhale · error
Cannot resume agent {agent_id}: status is {} ({})
Error message
Cannot resume agent {agent_id}: status is {} ({}) What it means
resume_from_checkpoint_with_policy gates on a ResumePolicy: InterruptedOnly accepts only Interrupted agents, InterruptedOrCompleted also accepts Completed. When the agent's actual status does not satisfy the requested policy, the resume is refused with the status name and the policy description. The policy exists so that, for example, an interrupted-only resume path can never silently resurrect an already-completed agent.
Source
Thrown at crates/tui/src/tools/subagent/mod.rs:5683
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 0c42157ee5)
Solutions
- Derive the policy from the agent's current status instead of hardcoding it (Interrupted -> InterruptedOnly; Completed -> InterruptedOrCompleted)
- Prefer the higher-level continue_child_from_user, which selects the correct policy per status
- Re-check status with get_result_by_ref right before resuming and treat a mismatch as a signal to re-plan, not to retry the same policy
Example fix
// before
let resumed = manager.resume_from_checkpoint_with_policy(
handle, runtime, &id, &text, ResumePolicy::InterruptedOnly)?;
// after
let snap = manager.get_result_by_ref(&id)?;
let policy = match snap.status {
SubAgentStatus::Interrupted(_) => ResumePolicy::InterruptedOnly,
SubAgentStatus::Completed => ResumePolicy::InterruptedOrCompleted,
other => anyhow::bail!("status {other:?} cannot resume"),
};
let resumed = manager.resume_from_checkpoint_with_policy(
handle, runtime, &id, &text, policy)?; Defensive patterns
Strategy: type-guard
Validate before calling
// Choose the policy from observed status instead of a constant.
let snap = manager.get_result_by_ref(&agent_id)?;
let policy = match snap.status {
SubAgentStatus::Interrupted(_) => ResumePolicy::InterruptedOnly,
SubAgentStatus::Completed => ResumePolicy::InterruptedOrCompleted,
other => anyhow::bail!("status {other:?} has no resume policy"),
}; 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
Catch 'Cannot resume agent' and re-read status; if it transitioned (e.g., interrupted -> completed), recompute the policy and retry once — further mismatches mean the agent is dead.
Prevention
- Never hardcode InterruptedOnly for generic resume flows
- Prefer continue_child_from_user, which owns policy selection, over calling the policy seam directly
- Re-check status adjacent to the resume call to shrink race windows
When it happens
Trigger: Calling resume with ResumePolicy::InterruptedOnly on a Completed agent; calling resume on Failed, Cancelled, or BudgetExhausted agents (no policy accepts them); a status race where the agent transitions (e.g., interrupted -> completed) between the caller's decision and the resume call.
Common situations: Orchestration code hardcoding InterruptedOnly for all resumes; user-initiated 'continue' racing an agent that finishes on its own; mixing up the interrupt-resume path with the completion-continuation path after an API change.
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 follow up agent {agent_id}: status is {} and the chil
- Cannot continue agent {agent_id}: no runtime is available to
- Cannot continue agent {agent_id}: status is {} and the child
- Agent {agent_id} has no continuable checkpoint to resume fro
- Cannot resume agent {agent_id}: sub-agent depth limit reache
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/1b5f56bfced62653.
Report an issue: GitHub.