fix(host-service): classify worktree-gone terminal failures as NOT_FOUND

Merged
SA
3mo ago
+10-0

Problem

HOST-SERVICE-1N (14 events on 1.20.2): when a workspace's worktree directory is deleted while a terminal pane is still open, every terminal.snapshot poll throws INTERNAL_SERVER_ERROR and the Sentry middleware reports it as a 500 — even though a worktree removed underneath an open terminal is a routine lifecycle condition, not an internal failure.

Root cause

createTerminalSessionInternal (the adoption path under snapshotSession/writeFramedInputToSession) returns the plain string error Workspace worktree no longer exists: <path> when the worktree directory is gone. The router's toTerminalIoError helper name-checks a few known messages ("belong" → FORBIDDEN; "not found"/"not active"/"exited" → NOT_FOUND), but this message matches none of them, so it falls through to the INTERNAL_SERVER_ERROR branch and the dumb 500=report Sentry middleware files it on every poll.

No typed error class crosses this boundary — the runtime returns { error: string } — so the classification has to match the stable message prefix.

Fix

Add a branch to toTerminalIoError that recognizes the Workspace worktree no longer exists prefix and returns NOT_FOUND with cause: { kind: "WORKTREE_GONE" }. The message and all other behaviour are unchanged; genuine unexpected terminal I/O failures still fall through to INTERNAL_SERVER_ERROR and keep reporting.

All terminal procedures that funnel errors through this helper (send, snapshot) pick up the fix; there are no per-procedure copies.

Verification

$ bunx biome check packages/host-service/src/trpc/router/terminal/terminal.ts
Checked 1 file in 12ms. No fixes applied.

$ cd packages/host-service && bun run typecheck
$ tsc --noEmit --emitDeclarationOnly false
typecheck exit=0

No existing tests cover this helper (grep -rl "toTerminalIoError" **/*.test.ts → no matches), so no test run applies.

Refs HOST-SERVICE-1N

https://claude.ai/code/session_0c69890b-c39f-420c-b03a-8038231a89ad


Summary by cubic

Classifies "Workspace worktree no longer exists..." terminal errors as NOT_FOUND in host-service instead of INTERNAL_SERVER_ERROR, addressing HOST-SERVICE-1N and stopping false 500s/Sentry alerts. Old: terminal.snapshot and send returned 500; New: they return 404 with cause { kind: "WORKTREE_GONE" }; message unchanged.

Review notes

  • Change is isolated to toTerminalIoError; both procedures inherit it; other errors keep their codes.
  • No tests updated; the helper had no coverage.

Migration

  • Update any client logic that treated deleted worktree terminals as 500 to handle 404 NOT_FOUND instead.
  • No action needed if you already treat missing/closed sessions as NOT_FOUND.

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling when a workspace worktree no longer exists.
    • Users now receive a clear “not found” error with a specific worktree-related cause.