[PR #12892] fix: handle missing session files gracefully on startup #14422

Closed
opened 2026-02-16 18:19:13 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/12892

State: closed
Merged: No


Problem

When launching opencode-desktop, the app throws NotFoundError to stderr for session JSON files that no longer exist on disk:

NotFoundError: NotFoundError
 data: {
  message: "Resource not found: ~/.local/share/opencode/storage/session/global/ses_*.json",
}
      at <anonymous> (src/storage/storage.ts:205:15)

This happens because the frontend tries to restore previously active sessions (via GET /session/:sessionID) that have since been deleted or cleaned up. The error propagates through the Hono error handler and gets printed to stderr, making it look like a crash.

Root Cause

  1. The frontend persists session references (URLs, active session state) across restarts
  2. When session files are deleted/cleaned up between runs, Session.get() throws NotFoundError
  3. The global onError handler logs this at error level and Bun displays the full stack trace to stderr
  4. Storage.list() uses a broad **/* glob that could match non-JSON files (lock files, temp files), creating phantom entries

Changes

packages/opencode/src/server/routes/session.ts

  • Catch NotFoundError in GET /session/:sessionID and return a clean 404 response directly, bypassing the global error handler

packages/opencode/src/server/server.ts

  • Downgrade NotFoundError from log.error to log.warn in the global onError handler — 404s are expected operational behavior, not application errors

packages/opencode/src/storage/storage.ts

  • Narrow Storage.list() glob from **/* to **/*.json to prevent listing non-JSON files (lock files, temp files, etc.) as storage entries

packages/opencode/src/session/message-v2.ts

  • Add defensive .catch() in MessageV2.parts() to skip missing part files instead of failing the entire message load (consistent with the pattern used in Session.list() and Session.children())

Testing

  • All 903 existing tests pass
  • Full typecheck passes across all 12 packages

Closes #12889

**Original Pull Request:** https://github.com/anomalyco/opencode/pull/12892 **State:** closed **Merged:** No --- ## Problem When launching `opencode-desktop`, the app throws `NotFoundError` to stderr for session JSON files that no longer exist on disk: ``` NotFoundError: NotFoundError data: { message: "Resource not found: ~/.local/share/opencode/storage/session/global/ses_*.json", } at <anonymous> (src/storage/storage.ts:205:15) ``` This happens because the frontend tries to restore previously active sessions (via `GET /session/:sessionID`) that have since been deleted or cleaned up. The error propagates through the Hono error handler and gets printed to stderr, making it look like a crash. ## Root Cause 1. The frontend persists session references (URLs, active session state) across restarts 2. When session files are deleted/cleaned up between runs, `Session.get()` throws `NotFoundError` 3. The global `onError` handler logs this at `error` level and Bun displays the full stack trace to stderr 4. `Storage.list()` uses a broad `**/*` glob that could match non-JSON files (lock files, temp files), creating phantom entries ## Changes ### `packages/opencode/src/server/routes/session.ts` - Catch `NotFoundError` in `GET /session/:sessionID` and return a clean 404 response directly, bypassing the global error handler ### `packages/opencode/src/server/server.ts` - Downgrade `NotFoundError` from `log.error` to `log.warn` in the global `onError` handler — 404s are expected operational behavior, not application errors ### `packages/opencode/src/storage/storage.ts` - Narrow `Storage.list()` glob from `**/*` to `**/*.json` to prevent listing non-JSON files (lock files, temp files, etc.) as storage entries ### `packages/opencode/src/session/message-v2.ts` - Add defensive `.catch()` in `MessageV2.parts()` to skip missing part files instead of failing the entire message load (consistent with the pattern used in `Session.list()` and `Session.children()`) ## Testing - All 903 existing tests pass - Full typecheck passes across all 12 packages Closes #12889
yindo added the pull-request label 2026-02-16 18:19:13 -05:00
yindo closed this issue 2026-02-16 18:19:13 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#14422