Skip to content

desktop: sessions missing from server cannot be deleted (DELETE 404 not handled) #51940

Closed

Description

@wthsama

Summary

The desktop app shows "ghost" sessions that exist only in local state (drafts.sqlite) but not on the server. Deleting them calls DELETE /api/session/{id}, the server responds 404 SessionNotFoundError, and the app treats this as a failure without cleaning up its local references — so the ghost entry can never be removed from the UI.

Environment

  • opencode version: 2.0.18 (desktop app, sidecar service opencode-cli.exe serve --service)
  • OS: Windows_NT 10.0.26200 (win32 x64)
  • Terminal: N/A (desktop app)
  • Shell: cmd.exe / PowerShell
  • Install/channel: desktop app, latest
  • Active plugins: oh-my-openagent (fails to load: "Plugin must export a default definition with an id and an effect or setup function")

Reproduction

  1. Get a session entry in the desktop app that has no server-side record. On my machine this happened naturally: during a service port conflict (see Additional Context), 8 sessions were created in a ~28h window and were never persisted to the server database.
  2. The ghost sessions still appear in the workspace session list — local references survive in %APPDATA%\ai.opencode.desktop\drafts.sqlite:
    • document table: opencode.workspace.<ws>.dat:session:<id>:prompt (empty prompt draft)
    • state table: opencode.browser.dat|sidecar row keyed by the session id
  3. Click delete on such a session.
  4. The app calls DELETE /api/session/<id> → server responds 404 {"_tag":"SessionNotFoundError",...} → the app reports a delete failure and keeps the entry.
  5. The entry is permanently undeletable from the UI.

Expected Behavior

A 404 SessionNotFoundError on delete should be treated as "already gone": remove the local references (prompt draft, browser sidecar state) and drop the entry from the list. Optionally, the session list should not render entries that have only local draft state with no server backing (or should render them as discardable drafts).

Actual Behavior

Delete fails with an error and the ghost session stays in the list forever. Verified server-side evidence:

  • Server log: DELETE /api/session/ses_f16d31626ffeONweIVod05774k http.status=404 (attempts at 2026-09-28T18:01:52Z and 2026-09-28T20:21:43Z, and again after a full service restart)
  • The session id is absent from both session_v2 and session tables in the server database (checked read-only)
  • All 8 ghost sessions have empty prompt drafts and no messages anywhere

Additional Context

Origin of the ghost sessions (why they have no server record): on 2026-09-28 between 17:41-17:53 UTC the log shows dozens of Managed service port 49374 on 127.0.0.1 is already in use by another process errors (then port 49375 as well) — multiple service instances were fighting. Sessions created in that window were never persisted; after the service situation settled, they only lived on in the desktop app's local state.

Workaround (manual, requires quitting the app): delete the leftover rows from drafts.sqlite — the document row ...:session:<id>:prompt and the state row opencode.browser.dat|sidecar / <session id> — then restart the app.

Frequency: consistently reproducible for every ghost session; the creation of ghosts itself was a one-time event tied to the service conflict window.

Activity

  1. github-actions commented on Sep 28, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of an existing issue. Please check:

    • #47769: reports undeletable ghost sessions after DELETE /api/session/{id} fails.
  2. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report, including the server log and the drafts.sqlite details. I couldn't reproduce this here: it needs the desktop app, and this sandbox can only run the CLI/TUI, which uses a different client.

    Reading the current code, the behaviour you describe looks expected from it. When the server answers 404 SessionNotFoundError, the desktop delete handles it like any other failure. It shows the "delete failed" toast and never runs the cleanup that drops the tab and local session state, so an entry with no server record can't be removed from the UI. A maintainer with the desktop app will need to confirm it. Until then, the manual cleanup of drafts.sqlite you described (with the app closed) is the workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions