{"record":{"id":"1feedc765bda47fe","repo":"Hmbown/CodeWhale","slug":"source-already-has-a-continuation-address-it-with-followup","errorCode":null,"errorMessage":"Source already has a continuation; address it with followup","messagePattern":"Source already has a continuation; address it with followup","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":6953,"sourceCode":"            narrow_optional_limit(runtime.worker_profile.wall_deadline_ms, source_deadline)\n                .map_or(requested_deadline, |deadline| {\n                    deadline.min(requested_deadline)\n                });\n        if deadline_ms <= now_ms {\n            return Err(anyhow!(\n                \"child wall-time budget exhausted; continuation cannot reset its deadline\"\n            ));\n        }\n        let wall_time = Duration::from_millis(deadline_ms - now_ms);\n        let continuation_from = if options.checkpoint_continuation {\n            let source = options\n                .resume_from_agent_id\n                .as_deref()\n                .ok_or_else(|| anyhow!(\"Checkpoint continuation requires a source agent\"))?;\n            let source =\n                self.resolve_agent_ref_for_session(&runtime.context.state_namespace, source)?;\n            if self.resume_targets.contains_key(&source) {\n                return Err(anyhow!(\n                    \"Source already has a continuation; address it with followup\"\n                ));\n            }\n            Some(source)\n        } else {\n            None\n        };\n\n        if let Some(model) = options.model.as_deref() {\n            runtime.model = model.to_string();\n        }\n        let effective_model = runtime.model.clone();\n        let agent_id = format!(\"agent_{}\", &Uuid::new_v4().to_string()[..8]);\n        // Admission into the turn-owned barrier happens before worker records,\n        // mailbox events, or task scheduling. Once turn settlement closes the\n        // registry, a racing descendant is refused rather than escaping the\n        // one-shot join and publishing after TurnComplete.\n        let foreground_child_registration = runtime.foreground_child_registration(&agent_id)?;","sourceCodeStart":6935,"sourceCodeEnd":6971,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/subagent/mod.rs#L6935-L6971","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nspawn(AgentSpawnOptions {\n    checkpoint_continuation: true,\n    resume_from_agent_id: Some(agent_id.clone()),\n    ..Default::default()\n})?;\n// after\nfollowup(&existing_continuation_agent_id, \"continue the task\")?;","handlingStrategy":"validation","validationCode":"// before spawning a continuation, check the source is not already continued\n// (via the listing/status tool: no live continuation child references source_agent_id)\nassert(!existingContinuations.some(c => c.sourceAgentId === sourceId), \"source already continued; use followup\");","typeGuard":null,"tryCatchPattern":"match spawn_result {\n    Err(e) if e.to_string().contains(\"already has a continuation\") => followup(existing_continuation_id, msg),\n    other => other?,\n}","preventionTips":["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."],"tags":["subagent","state-conflict","duplicate-operation"],"backgroundTag":"invalid-state-transition","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"}