Hmbown/CodeWhale · error
Agent continuation target is outside the active session
Error message
Agent continuation target is outside the active session
What it means
Thrown by `continuation_target` when a successor in the resume chain belongs to a different owner session than the source agent (or the source has an empty owner). Continuations may only fork within the active session; crossing sessions would leak conversation state, so the walk refuses.
Solutions
- Only continue agents that belong to the currently active session; filter the roster by owner_session_id first.
- If cross-session continuation is genuinely needed, import the lineage into the active session with a valid owner instead of forking it in place.
- Fix data that was loaded with an empty owner_session_id (re-associate the record with the active session).
- Spawn a fresh child in the current session carrying the needed context instead of resuming a foreign lineage.
Example fix
// before
let outcome = registry.continue_agent(&foreign_agent_id, text)?;
// after
if registry.owner_session_of(&foreign_agent_id).as_deref() != Some(active_session_id) {
anyhow::bail!("agent belongs to another session; spawn a child in this session instead");
}
let outcome = registry.continue_agent(&foreign_agent_id, text)?; Defensive patterns
Strategy: validation
Validate before calling
let owner = registry.owner_session_of(agent_id);
if owner.as_deref() != Some(active_session_id) {
anyhow::bail!("agent {agent_id} belongs to session {:?}, not the active session", owner);
} Type guard
fn belongs_to_session(owner: &Option<String>, active: &str) -> bool {
owner.as_deref() == Some(active) && !active.is_empty()
} Try / catch
match registry.continue_agent(&handle, agent_ref, text, runtime) {
Err(e) if e.to_string().contains("outside the active session") => {
// spawn a fresh child in this session instead
registry.spawn_child_with_context(&text)?;
}
r => r?,
} Prevention
- Filter the agent roster by owner_session_id before offering continue/follow-up actions.
- Never reuse agent ids across session switches.
- Ensure restored records always carry a non-empty owner_session_id.
- Treat cross-session continuation as unsupported; copy context into a new child.
When it happens
Trigger: Calling continue/follow-up for an agent whose `resume_targets` successor has an `owner_session_id` different from the source's owner — e.g. resuming an agent carried over from a previous session — or when the source's owner_session_id is empty.
Common situations: Restoring persisted subagent state into a new session and continuing an old lineage; passing an agent id from a detached/foreign session to the active registry; records loaded without owner metadata (empty owner string).
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
- Agent continuation target is no longer retained
- Agent not found
- Agent session not found
- Agent session name ' ' is ambiguous; use an agent_id
- agent should stay registered
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/c9a8d0dc08cefcec.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:6004
/// the original root conversation; malformed or cyclic state fails closed.
fn continuation_target(&self, agent_id: &str) -> Result<String> {
let source = self
.agents
.get(agent_id)
.ok_or_else(|| anyhow!("Agent not found"))?;
let owner = &source.owner_session_id;
let mut target = agent_id.to_string();
let mut seen = HashSet::new();
while let Some(next) = self.resume_targets.get(&target) {
if !seen.insert(target.clone()) {
return Err(anyhow!("Invalid agent continuation lineage: cycle"));
}
let successor = self
.agents
.get(next)
.ok_or_else(|| anyhow!("Agent continuation target is no longer retained"))?;
if owner.is_empty() || successor.owner_session_id != *owner {
return Err(anyhow!(
"Agent continuation target is outside the active session"
));
}
target.clone_from(next);
}
Ok(target)
}
fn continuation_source(&self, agent_id: &str) -> Option<String> {
self.resume_targets.iter().find_map(|(source, target)| {
(target == agent_id && self.continuation_target(source).is_ok()).then(|| source.clone())
})
}
pub(super) fn continuation_target_for_caller(
&self,
active_session_id: &str,
agent_ref: &str,View on GitHub (pinned to 73e0f67d83)