a task the server cannot find is dismissed, not reported

A chip stuck on "running" could not be stopped, killed or dismissed. Stop and
Kill both answered {"stopped":false,"reason":"no such task"} — there is no
output file, so no pid, so nothing to signal — and dismiss is only offered for a
task the tray believes has finished. A chip with no way out.

The server saying it cannot find the job is authoritative rather than an error
worth reporting: the chip was the last thing claiming it existed. Pressing Stop
now clears it.

Running chips still have no dismiss button of their own, deliberately — the
tray is the only thing watching a live job and a hidden one is a job you have no
way back to. This is the escape hatch for a job that is not actually live, and
it is reached by pressing the control you would already have pressed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-19 14:41:29 +00:00
co-authored by Claude Opus 5
parent 9c6534c746
commit 0f56aae803
@@ -82,7 +82,19 @@ export const BackgroundTaskTray = ({ messages, sessionId }: BackgroundTaskTrayPr
try {
await client.delete(`/chat/tasks/${taskId}${force ? '?force=1' : ''}`);
} catch (err) {
toast.error(err instanceof Error ? err.message : 'Could not stop that job');
const message = err instanceof Error ? err.message : '';
// The server saying it cannot FIND the job is authoritative, not an error to report: there is no
// output file, therefore no pid, therefore nothing running. The chip was the last thing claiming
// otherwise.
//
// Without this the tray showed a job that could not be stopped, killed or dismissed — a chip with
// no way out, because dismiss is only offered for a task the tray believes has finished. Pressing
// Stop then Kill both answered {"stopped":false,"reason":"no such task"} and changed nothing.
if (message.includes('no such task') || message.includes('already stopped')) {
dismiss(taskId);
return;
}
toast.error(message || 'Could not stop that job');
}
};