Repository navigation
Description
Summary
After the desktop sidecar process takes over (v2.0.12+), no message or part rows are written to opencode.db — ever. session_v2 rows still update, and model requests are still made to the LLM backend (confirmed via llama-swap access logs), but nothing persists. Sessions appear to be "working" indefinitely with zero visible token output.
Reproduction
- Run opencode desktop app (any 2.x version, sidecar ≥ 2.0.12)
- Start a new session or continue an existing one
- Send a prompt
- Observe: session shows "working", model request fires (visible in backend logs), but no tokens appear in UI
- Check DB:
SELECT COUNT(*) FROM part WHERE created_at > '...'→ zero new rows since sidecar startup
Evidence
From a live installation (opencode-desktop 1.18.31, sidecar auto-updated 2.0.12 → 2.0.15):
-- Last message row written:
SELECT MAX(created_at) FROM message;
-- 2026-09-22 18:39:40 (the exact minute the 2.0.12 sidecar started)
-- Last part row written:
SELECT MAX(created_at) FROM part;
-- 2026-09-22 18:40:04
-- Parts on 09-23 (next day, across ALL sessions including a fresh one):
SELECT COUNT(*) FROM part WHERE date(created_at) = '2026-09-23';
-- 0
-- But session_v2 rows DO update:
SELECT MAX(updated_at) FROM session_v2;
-- 2026-09-23 20:22:38 (fresh session, still "working")Backend confirmed model requests succeeded (llama-swap access log):
200 OKwith 1.65MB response body at ~20:30 (7m38s duration)200 OKwith 1.63MB response body at ~20:35 (4m9s duration)200 OKwith 586KB response body at ~20:40 (8m15s duration)- Plus multiple
499client aborts at ~5-6min (opencode client timeout)
Schema context
The v2 migration (20260923013825_project_time_active) introduced the new session_v2/message/part schema where part.message_id is NOT NULL (FK to message). No foreign key violations or errors appear in the log — the write simply never happens.
Impact
- All sessions are wedged: they show "working" forever, no tokens visible
- User cannot see any model output in the UI
- The model IS being called (tokens are generated server-side) but the results are never persisted
- Affects all sessions simultaneously (old + new)
- No workaround found
Environment
- opencode desktop: 1.18.31 (AUR
opencode-desktop-bin) - Sidecar: 2.0.12 (initial) → 2.0.15 (auto-updated)
- OS: Arch Linux
- DB:
~/.local/share/opencode/opencode.db(1.03GB, 165 sessions, 19112 message rows, 69755 part rows — all pre-2026-09-22 18:40) - Model: local llama-server via llama-swap (OpenAI-compatible API at
http://192.168.2.215:11436/v1)
Log
No errors in ~/.local/share/opencode/log/opencode.log. The sidecar process runs serve --service and appears healthy.
Workaround
Downgrade to v1 desktop (1.18.x) — but this requires a fresh database since v1 cannot read the v2-migrated schema. All session history is inaccessible (data is intact in the v2 DB, just unreadable by v1).
Activity
Dante-dan commentedon Oct 8, 2026
I compared this report with the current
v2source at0621ea9. The current projector persists updates throughSessionMessageUpdaterintosession_message, whose schema is defined here. That differs from thesession_v2/message/parttables described in this report. The migration named20260923013825_project_time_activeadds project activity tracking; this source check does not reproduce the reported desktop sidecar behavior or establish its root cause.Could you share the exact sidecar version/build that exhibits this, and whether its database has advancing durable
eventrows while the UI stays in “working”? A sanitized schema listing for the affected database (sqlite_mastertable names and the relevant columns for the message/event tables) would also help identify which persistence path and version to trace. Please omit local paths, credentials, and tokens.famewolf commentedon Oct 8, 2026
Data from the affected installation, as requested.
1. Versions
1.18.31-1(AURopencode-desktop-bin, Arch Linux)serve --serviceon v2.0.18 (uptime > 2 days), plus a secondserve --hostname 127.0.0.1 --port 43513instance2. Do durable
eventrows advance while the UI stays "working"?No. On the affected database nothing advances at all:
eventcreated= 0 for every row — column never populated, no new rowsmessagepartsession_messagesession_v2(maxtime_updated)Notes:
session_v2kept advancing for about a day aftermessage/partactivity stopped, then froze too.eventrows, nosession_v2updates, no FK violations, no errors in the log — the write simply never happens, matching the report.3. Sanitized schema listing
Affected database — 24 tables:
account, account_state, control_account, credential, event, event_sequence, instruction_blob, instruction_entry, instruction_state, kv, message, migration, part, permission, project, project_directory, session, session_inbox, session_message, session_pending, session_share, session_v2, todo, workspace, worktreeAll timestamps are unixepoch milliseconds.
One more finding relevant to your source check
The current v2 runtime writes to its own data directory, whose database has no
message/parttables at all — its schema issession_v2+session_message+eventonly. On sidecar 2.0.18 that path is healthy:session_messagehas 17,965 rows,session_v2has 140, and the WAL file is being rewritten continuously while sessions are active (checked 2026-10-08; last write within the same minute as the check). That database'seventtable has 0 rows.So the observed timeline is consistent with your reading of
0621ea9: themessage/partschema from this report stopped receiving writes after 2026-09-27, and current versions persist throughsession_messageviaSessionMessageUpdater. On 2.0.18 the session persistence behaves normally — no reproduction of the reported silence on that path.Dante-dan commentedon Oct 8, 2026
Thanks, this separates the inactive database from the healthy v2.0.18 persistence path.
One additional source detail: the V1 migration runner returns immediately once its migration state is
completed; completion is recorded here. This is a one-time import into the V2 model, not ongoing writes back to the legacymessage/parttables. Their last-write timestamps alone therefore cannot diagnose a current V2 persistence failure. The CLI database selection also depends onOPENCODE_DB, the data root, and the release channel, so two databases need not be the same active runtime store.Your current
session_message/WAL activity is consistent with the current writer. It does not establish what caused the original 2.0.12–2.0.15 UI stall or whether the historical sessions imported successfully. Those remain separate questions; the missing original database and the absence of a failure on the current active path prevent assigning a persistence root cause from these counts. I have not reproduced the historical desktop failure or verified its migration outcome.famewolf commentedon Oct 9, 2026
Fair points, all four taken:
message/partlast-write timestamps cannot diagnose a current V2 persistence failure. Dropping that leg.OPENCODE_DB, the data root, and the release channel. Next data from this side: the active-store identification from the affected setup, so both sides look at the same database.session_message/WAL activity being consistent with the current writer is noted — that covers the healthy path, not the historical one.Net of it: no reproducible root cause on the current path, and the historical failure cannot be recreated from what is available. Any new information from this setup gets reported back here.
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report! Before we can reproduce this, a few things need checking.
About the database evidence: in v2, conversation content is no longer written to the v1
message/parttables. It goes tosession_message(alongsidesession_v2). So seeing no new rows inmessage/partafter the migration is expected and doesn't by itself mean anything is failing. Could you check whether new rows appear there instead, e.g.:A possible cause: by default v2 waits 300 seconds for a provider to start responding (
headerTimeout). Your llama-swap logs show requests taking 4–8 minutes and499aborts at about 5–6 minutes, which fits a local server that takes longer than that on a large prompt. If you can, try raisingheaderTimeout(in milliseconds) in your provider's settings, or try a small prompt in a fresh session, and see whether output appears.It would also help to have, in your own words and briefly:
opencode --versionfor the sidecar and the desktop app version you're running now~/.local/share/opencode/log/from the time a session was stuck, even if they aren't errorsYou can reply here with the details, or edit the issue. If you edit it, please also leave a comment saying you've updated it so we know you're done.
famewolf commentedon Oct 29, 2026
Replying to the bot's 2026-10-28T06:31:37Z evidence request. Box: opencode v2.2.0 (sidecar/server). No separate desktop client on this host; the client is the web UI over the sidecar, so both resolve to v2.2.0 here.
Live DB (v2 schema, 20 tables): session_message has 58601 rows; newest time_created = 1793206035903 (≈ 2026-10-28, today). session_v2 has 372 rows. There is no separate part/p1 table in this schema — parts are embedded in the message row (so a "part persistence failure" would have to be inside the message-row write path, not a missing table).
headerTimeout: live config (opencode.jsonc lines 276-277) sets both
timeoutandheaderTimeoutto 3600000 ms (1 hour). The 300 s default is already overridden on this box, so the 499 s stall is not explained by the default timeout alone.Repro: none on this box at check time. The 09-24 incident window is gone from the log directory (only opencode.log remains, 1611 lines, oldest entry 2026-10-26T21:21Z), so the original stuck-period lines are unavailable. If it recurs, the log around the stall is the next useful data point.
Small hosted-model test: not run this pass (would need a fresh session plus a hosted model; the symptom is intermittent and not reproducible here). A controlled data point is available on request.
graphicsMode=direct: 237 rows in the T9 table (from the earlier probe).
If any of the above numbers look off (e.g. the MAX timestamp conversion), the raw value 1793206035903 is the canonical one.
opencodejr commentedon Oct 31, 2026
We're closing this for now because we haven't heard back. We needed a few details before we could reproduce it.
To recap: in v2, conversation content goes to
session_message, not the v1message/parttables, so the database evidence in the report doesn't by itself show a persistence failure. The499aborts at about 5–6 minutes may be v2's default 300-secondheaderTimeoutwith a slow local server, and raising it may help.If sessions still get stuck, please open a new issue with the output of
opencode --version, whether newsession_messagerows appear, what you see in the UI, and the log lines from the time it happened, and we'll take another look. Thanks!famewolf commentedon Oct 31, 2026
Your bot needs to learn how to read. I replied 2 days ago.