Hmbown/CodeWhale · error
Source already has a continuation; address it with followup
Error message
Source already has a continuation; address it with followup
What it means
When a checkpoint continuation is requested, the launcher checks `resume_targets` to ensure the source agent does not already have a pending continuation. Each checkpointed agent may be continued only once at a time; a second continuation would fork its state incoherently. The error tells the caller to address the existing continuation via the followup path instead.
Solutions
- Do not spawn a new continuation; use the followup tool against the existing continuation agent instead.
- Check the source agent's status/listing to find the already-created continuation and interact with that one.
- If the prior continuation is dead and settled, wait for it to settle (or cancel it) so it leaves resume_targets, then retry.
Example fix
// before
spawn(AgentSpawnOptions {
checkpoint_continuation: true,
resume_from_agent_id: Some(agent_id.clone()),
..Default::default()
})?;
// after
followup(&existing_continuation_agent_id, "continue the task")?; Defensive patterns
Strategy: validation
Validate before calling
// before spawning a continuation, check the source is not already continued // (via the listing/status tool: no live continuation child references source_agent_id) assert(!existingContinuations.some(c => c.sourceAgentId === sourceId), "source already continued; use followup");
Try / catch
match spawn_result {
Err(e) if e.to_string().contains("already has a continuation") => followup(existing_continuation_id, msg),
other => other?,
} Prevention
- Track continuations you launched per source agent in caller-side state.
- On retry after a spawn failure, first check whether the continuation actually registered before re-spawning.
- Prefer the followup tool for iterating on a checkpointed agent.
When it happens
Trigger: Calling spawn with checkpoint_continuation = true and resume_from_agent_id = X when X already appears in the manager's resume_targets map (i.e. a continuation for X was already launched and is still tracked).
Common situations: Retrying a spawn after a timeout or error without realizing the first continuation actually registered; a parent loop launching continuations for the same checkpoint twice; concurrent tool calls in one turn both resuming the same agent.
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
- bundle already installed; use
- agent action=claim widens an enforced write scope, and the…
- Agent has no continuable checkpoint to resume from…
- Agent not found
- Agent continuation target is no longer retained
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1feedc765bda47fe.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:6953
narrow_optional_limit(runtime.worker_profile.wall_deadline_ms, source_deadline)
.map_or(requested_deadline, |deadline| {
deadline.min(requested_deadline)
});
if deadline_ms <= now_ms {
return Err(anyhow!(
"child wall-time budget exhausted; continuation cannot reset its deadline"
));
}
let wall_time = Duration::from_millis(deadline_ms - now_ms);
let continuation_from = if options.checkpoint_continuation {
let source = options
.resume_from_agent_id
.as_deref()
.ok_or_else(|| anyhow!("Checkpoint continuation requires a source agent"))?;
let source =
self.resolve_agent_ref_for_session(&runtime.context.state_namespace, source)?;
if self.resume_targets.contains_key(&source) {
return Err(anyhow!(
"Source already has a continuation; address it with followup"
));
}
Some(source)
} else {
None
};
if let Some(model) = options.model.as_deref() {
runtime.model = model.to_string();
}
let effective_model = runtime.model.clone();
let agent_id = format!("agent_{}", &Uuid::new_v4().to_string()[..8]);
// Admission into the turn-owned barrier happens before worker records,
// mailbox events, or task scheduling. Once turn settlement closes the
// registry, a racing descendant is refused rather than escaping the
// one-shot join and publishing after TurnComplete.
let foreground_child_registration = runtime.foreground_child_registration(&agent_id)?;View on GitHub (pinned to 73e0f67d83)