Repository navigation
Description
Summary
Sessions whose rows only exist in the V1 session table are invisible in V2: they
are missing from the session/tab list, GET /api/session/<id> returns 404,
opencode session export <id> answers Session not found, and the desktop app
shows "This tab points to a session that no longer exists on this server". The
session data itself (messages and parts) is intact in the V1 tables — it is a
read-path/projection problem, not data loss.
Environment
- opencode version: 2.0.28 (desktop app + its bundled CLI
cli/2.0.28-arm64/opencode-cli serve --service); homebrew CLI on the same machine is 2.0.25 - OS: Darwin 25.6.0 (darwin arm64), macOS desktop app
- Terminal: Unavailable: desktop app (no
$TERM_PROGRAM); reproduced with the CLI too - Shell: /bin/zsh
- Install/channel: release/latest (desktop app 2.0.28 + homebrew 2.0.25)
- Active plugins: none
Reproduction
- On a profile that has been writing sessions with an older version (rows present in
the V1session,message,parttables), let some sessions be written only to
the V1 tables (see Additional Context for the observed boundary). - Start opencode 2.0.28 against that same
opencode.db. - Observe
GET /api/session/<id>→404for those ids (4 ids requested on app start,
in the restored tabs), andopencode session list/ the tab list omitting them.
Verified in SQLite:
select count(*) from session; -- 89
select count(*) from session_v2; -- 81
select id, title, time_created from session
where id not in (select id from session_v2); -- 9 rows, all invisible
select count(*) from message where session_id = '<one of those>'; -- 451 messages, intact
select count(*) from session_message where session_id = '<same>'; -- 0Log evidence (server role):
message="Sent HTTP response" role=server http.method=GET http.url=/api/session/ses_ec98b257... http.status=404
message="Sent HTTP response" role=server http.method=GET http.url=/api/session/ses_ec98b257.../message http.status=404
message="Sent HTTP response" role=server http.method=GET http.url=/api/experimental/session/ses_ec98b257.../export http.status=404
Expected Behavior
Sessions that exist in the database should remain visible and openable after an
upgrade, either because the V1 rows are projected into session_v2 (fully), or
because the read path still falls back to the V1 tables. session export should
work for any session that exists in the database.
Actual Behavior
- The 9 sessions appear neither in the session list nor in tabs; the desktop UI shows
"This tab points to a session that no longer exists on this server" with the session id. - Every API call for them returns 404 (session, message, inbox, export).
opencode session export <id>printsSession not found, so the documented
export/import route cannot be used to rescue them.- The V1→V2 projection appears to have stopped partway: 80 sessions have rows in both
tables, but a contiguous range of later sessions (a ~2-day window) has V1 rows only.
Additional Context
- Observed boundary on this machine: the last session projected into
session_v2was
created2026-10-11 15:37; the first session existing only insessionwas created
2026-10-11 20:06. Everything created up to the migration boundary is dual-present. - The orphan rows carry
version = 1.18.35; the app was updated to 2.0.28 afterwards
(the first 2.0.28 session was written intosession_v2correctly). So this looks like
a partial/failed projection for rows written in between. - For a session present in both tables, the V1 tables turned out to be a superset of
what the projection stored: 293 V1 messages vs 213 exported, 81 messages never reached
session_v2. That suggests the projection also drops content, not only whole sessions. - Workaround used successfully: rebuild the export format from the V1 tables and import
it (opencode session import <file> --directory <dir>), which restores the sessions
with their original ids. Notes from doing that, in case they help fix the projection:session importpreservesinfo.idandinfo.time.created, and it creates
session_messagerows keyed by the ids in the JSON (a collision on
session_message.idfails withUNIQUE constraint failed: session_message.id,
surfaced as HTTP 500).inforequiresprojectID; content parts needtime.created(at least for
reasoning/tool); a toolstate.errormust be structured
({"type":"tool.execution","message":"..."}), not the string the V1 data holds.- With those applied, 159/212 common messages came out byte-identical to the official
export of a dual-present session; the only remaining differences were ±1 ms on
time.completedand cosmetic metadata (snapshot.files,state.attachments).
- Frequency: reproducible and permanent for the affected ids (not intermittent).
Activity
opencode-agent commentedon Oct 14, 2026
Thanks for the very thorough report and the recovery notes. I think this is a duplicate of #50130. Your orphan sessions carry
version = 1.18.35, so a V1 client wrote them after the one-time V1→V2 migration had already been markedcompleted. Once that happens, later V1 sessions are never imported, and that leads to the 404s and the "This tab points to a session that no longer exists on this server" message.Possible duplicates and related issues, ordered by likelihood:
migration.v1-v2completes are never imported (404, missing tabs, same desktop message). Open PR fix(core): import V1 sessions created after migration completes #54272 would make the migration pick up these newer sessions.kv.migration.v1-v2marker to force a re-run is destructive, and describe a non-destructive way to recover.Your import-based workaround notes would be a useful addition on #50130.
The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
opencode-agent commentedon Oct 15, 2026
Closing this as a duplicate of #50130, since we haven't heard back. Sessions that a V1 client (here 1.18.35) creates after the V1→V2 migration is marked
completedare never imported. That causes the 404s and the "This tab points to a session that no longer exists on this server" message. Open PR #54272 would make the migration pick these sessions up. Please follow #50130 for updates; your import-based workaround notes would be useful there. The missing messages in already-migrated sessions look like #53971. If your case turns out to be different, reply here and we can reopen.