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

  1. Do not spawn a new continuation; use the followup tool against the existing continuation agent instead.
  2. Check the source agent's status/listing to find the already-created continuation and interact with that one.
  3. 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

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


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)