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
- List the jobs visible to your current session (via the shell tool's job listing) and use one of those ids.
- Check whether the job already completed and was reaped — fetch its final output before it is removed.
- 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
- Always scope job ids to the session that created them.
- Fetch job output before it is reaped/removed.
- Handle 'not found' on follow-up calls as a normal completed-job outcome.
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
- Agent not found
- Agent continuation target is outside the active session
- Agent not found in the active session
- agent profile may not request allow_shell=true
- allowlisted read-only executable
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 orView on GitHub (pinned to 73e0f67d83)