Hmbown/CodeWhale · error · anyhow::Error

Agent session not found

Error message

Agent session {agent_ref} not found

What it means

The subagent tool resolves an agent reference (`agent_ref`, which may be a name or an agent_id) to exactly one agent session by collecting matching agent IDs. This error is thrown when the reference matches zero sessions, meaning the caller named an agent that does not exist in the current session's agent table.

Solutions

  1. Re-list available agents to get a valid agent_id and use that exact id
  2. Check whether the subagent already completed or was cancelled; start a new one if needed
  3. Fix the agent_ref spelling/whitespace and retry
  4. Verify the agent was spawned in the same active session, not a prior session

Example fix

// before
let id = resolve("my-agnt")?; // Err: Agent session my-agnt not found
// after
let agents = list_agents();
let id = agents.iter().find(|a| a.id == "my-agent").map(|a| a.id.clone()).ok_or_else(|| anyhow!("spawn agent first"))?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_agent_exists(agents: &[AgentInfo], agent_ref: &str) -> Result<&AgentInfo, String> {
    agents.iter().find(|a| a.id == agent_ref || a.name == agent_ref)
        .ok_or_else(|| format!("agent '{agent_ref}' not found; available: {:?}", agents.iter().map(|a| a.id.as_str()).collect::<Vec<_>>()))
}

Type guard

fn is_known_agent(agents: &[AgentInfo], agent_ref: &str) -> bool {
    agents.iter().any(|a| a.id == agent_ref || a.name == agent_ref)
}

Try / catch

match resolve_agent_ref(agent_ref) {
    Ok(id) => proceed(id),
    Err(e) if e.to_string().contains("not found") => refresh_agent_list_and_retry(),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling a subagent coordination tool (e.g. agent send/interrupt/status) with an `agent_ref` string that does not match any live SubAgent id or name, or referencing an agent whose session already terminated and was reaped.

Common situations: A typo in the agent name; using a stale agent_id captured before the agent finished; a subagent completing or crashing between listing agents and acting on one; passing a name that was never registered because the spawn failed.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/ce53f9d20de413b8. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/subagent/mod.rs:7518

                    .is_none_or(|session_id| self.agent_is_owned_by_session(agent, session_id))
            })
            .collect::<Vec<_>>();
        // A reused name shadows settled holders: the live worker wins, and
        // settled records stay id-addressable (#6313).
        if matches
            .iter()
            .any(|agent| !subagent_status_is_settled(&agent.status))
        {
            matches.retain(|agent| !subagent_status_is_settled(&agent.status));
        }
        let matches = matches
            .iter()
            .map(|agent| agent.id.clone())
            .collect::<Vec<_>>();

        match matches.as_slice() {
            [id] => Ok(id.clone()),
            [] => Err(anyhow!("Agent session {agent_ref} not found")),
            _ => Err(anyhow!(
                "Agent session name '{agent_ref}' is ambiguous; use an agent_id"
            )),
        }
    }

    fn agent_is_owned_by_session(&self, agent: &SubAgent, active_session_id: &str) -> bool {
        !active_session_id.is_empty() && agent.owner_session_id == active_session_id
    }

    fn agent_id_is_owned_by_session(&self, agent_id: &str, active_session_id: &str) -> bool {
        self.agents
            .get(agent_id)
            .is_some_and(|agent| self.agent_is_owned_by_session(agent, active_session_id))
    }

    /// Resolve a hierarchy mutation target and prove that it is a strict
    /// descendant of the calling agent. Root registries carry no caller id

View on GitHub (pinned to 73e0f67d83)