Hmbown/CodeWhale · error

Job not found

Error message

Job {task_id} not found

What it means

ShellManager's ownership check deliberately returns a single "Job {task_id} not found" error when the caller's active session does not own the job — including the case where the job exists but belongs to a different session. The comment in source makes the intent explicit: do not disclose whether the id exists in another session, so both missing and foreign jobs map to the same message.

Solutions

  1. List the jobs visible to your current session (via the shell tool's job listing) and use one of those ids.
  2. Check whether the job already completed and was reaped — fetch its final output before it is removed.
  3. Switch to (or re-check) the session that launched the job; job ids are session-scoped.

Example fix

// before
manager.kill("shell_abc123")?; // id from another session

// after
let jobs = manager.list_jobs(&active_session_id);
let job = jobs.iter().find(|j| j.id == "shell_abc123")
    .ok_or_else(|| anyhow!("no job shell_abc123 in this session"))?;
manager.kill(&job.id)?;
Defensive patterns

Strategy: validation

Validate before calling

// verify the id is visible in the current session before operating on it
let owned = manager.list_jobs(&active_session_id)
    .iter().any(|j| j.id == task_id);
if !owned { return Err(anyhow!("job {task_id} not found in this session")); }

Try / catch

// Rust: treat not-found as non-retryable; refresh the job list
match manager.kill(task_id) {
    Ok(()) => {}
    Err(e) if e.to_string().ends_with("not found") => {
        // re-list jobs; the job either completed or belongs to another session
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling a shell job operation (kill, read, wait, etc.) with a task_id that either does not exist at all, was already reaped, or exists but is owned by a different session than the active_session_id being checked.

Common situations: A background shell job finished and was removed before the follow-up call; using a job id from another TUI/session or a stale session id after reconnecting; copy-pasting a job id from logs of a different workspace.

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/fd204adf13b73a54. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/shell.rs:1852

                "foreground_background_requested",
                &self.foreground_background_requested,
            )
            .finish()
    }
}

impl ShellManager {
    fn require_session_owner(&self, task_id: &str, active_session_id: &str) -> Result<()> {
        let owned = self.processes.get(task_id).is_some_and(|shell| {
            !active_session_id.is_empty() && shell.owner_session_id == active_session_id
        }) || self.stale_jobs.get(task_id).is_some_and(|job| {
            !active_session_id.is_empty() && job.owner_session_id == active_session_id
        });
        if owned {
            Ok(())
        } else {
            // Do not disclose whether the id exists in another session.
            Err(anyhow!("Job {task_id} not found"))
        }
    }

    /// Create a new `ShellManager` with default (no sandbox) policy.
    pub fn new(workspace: PathBuf) -> Self {
        Self {
            processes: HashMap::new(),
            stale_jobs: HashMap::new(),
            default_workspace: workspace,
            sandbox_manager: SandboxManager::new(),
            sandbox_policy: ExecutionSandboxPolicy::default(),
            foreground_background_requested: false,
            output_spill_dir: None,
        }
    }

    /// Point lowercase-`bash` complete-output spill files at `dir` instead of
    /// the process temp dir. Tests use a nonexistent dir to simulate a full or

View on GitHub (pinned to 73e0f67d83)