Repository navigation
Description
Summary
After upgrading from OpenCode V1 to V2, sessions that were created in a non-git project directory disappear from the TUI sidebar and from opencode session list when run in that directory. The sessions are still in the database and remain reachable through the global session picker and through a directory-filtered API query, so no data is lost — they are simply never listed for the project.
Environment
- opencode version: 2.0.23 (npm
@opencode/cli, release channel: latest) - OS: Microsoft Windows 10 Pro, win32 x64
- Terminal:
TERM=xterm-256color, noTERM_PROGRAM/COLORTERM/WT_SESSION(Cygwin bash) - Shell:
C:\Windows\system32\cmd.exeas the user shell; opencodeshellis set toc:/tools/cygwin/bin/bash.exe - Active plugins:
opencode-working-memory(loaded from bothopencode.jsonpluginsandcli.jsonplugins)
Reproduction
- With V1 (1.18.34), work in a directory that is not a git repository and create several sessions, including subagent sessions. Repeat for a couple of directories.
- Install V2 (2.0.23). V2 reports the storage migration as done (
storage/migrationcontains2;GET /api/experimental/migration/v1returns{"status":"completed"}). - Start V2 in one of those directories.
- Observe the TUI sidebar and
opencode session listin that directory.
Expected Behavior
The sidebar and opencode session list in a directory should show the sessions previously created there, just like opencode session list does for git-backed directories.
Actual Behavior
Only sessions created by V2 after the upgrade are listed. In the reproduction directory:
$ opencode session list
ses_ef1c39c0dffeaGbYCNag2CgVHN Opencode sessions not visible (V2, current session)
# before the manual repair described below
$ opencode api get "/api/session?project=f47d456faacca9e42cf9043753505a4f46dfc274"
1 session
$ opencode api get "/api/session?directory=D%3A%2Fwork%2Fexample"
6 sessions
The sessions are intact and were found without difficulty in the global session picker, which confirms the loss is a listing/filtering problem rather than a storage problem.
Additional Context
Two independent defects stack up here. Both are required for the symptom, and fixing only one still leaves the sessions hidden.
1. V1 sessions are attributed to the pseudo-project global and are never re-homed
V1 stored sessions of every non-git directory under the special project id global (its project.worktree is the sentinel /). V2 instead creates one project row per directory. The session list is filtered by project_id, so V1-era sessions in non-git directories are unreachable from the project's session list:
-- after the upgrade
SELECT project_id, version, count(*), max(time_updated)
FROM session_v2 GROUP BY project_id ORDER BY count(*) DESC;
-- global | 1.14.19 .. 1.18.30 | 366 | ...
-- f47d456f... (worktree = D:/work/example) | 2.0.23 | 1 | ...The same directory holds six sessions, but the project-scoped query returns only the one created by V2:
SELECT id, project_id, version, path FROM session_v2
WHERE directory = 'D:/work/example';
-- ses_f6d5d693... global 1.18.30 MyDocs/My Devices/_lan/_OS/vm-iredmail
-- ses_f539f413... global 1.18.30 (subagent)
-- ses_ef1c39c0... f47d456f… 2.0.23 (NULL)migrateFromGlobal() does not repair this: it only runs when the target project row is created for the first time, so by the time V2 is started in an already-populated directory there is nothing to trigger it. The general project-id repair in Project.fromDirectory() matches stale projects by project.worktree, and the global project has worktree = '/', so it never matches a real directory either.
On the affected machine this accounts for 366 sessions across 85 directories (e.g. 71 sessions in one directory, 29 in another), all created between V1.4 and V1.18.
2. path must be ''; NULL is filtered out by the subpath query
After re-pointing project_id at the correct V2 project, the sessions were still missing from the sidebar. The TUI sends subpath= (empty string), and the project-scoped query filters path = '', which does not match NULL:
?project=f47d456f… -> 6 sessions
?project=f47d456f…&subpath -> 1 session
The single row that survives the subpath query is the V2 session, whose path is the empty string; the five repaired rows had path IS NULL and were dropped. Setting path = '' made all six appear. This is the path = '' edge case in the project listing path: rows migrated from V1 carry a NULL path (V1 recorded a relative path such as MyDocs/My Devices/_lan/_OS/vm-iredmail, relative to the global worktree /), and no code normalizes them to ''.
Manual repair used as a workaround
Reversible SQL, applied to session_v2 only:
UPDATE session_v2
SET project_id = '<project id for the directory>',
path = ''
WHERE project_id = 'global'
AND directory = 'D:/work/example';After this, ?project=<id>&subpath returns all six sessions and the TUI sidebar lists them. A full database backup was taken before the change.
Related
This looks like the same root cause family as the already-reported sessions-not-shown issues for non-git directories and for project-id drift (git init, history rewrite, /sessions scope). Per the V1→V2 migration guide, only three breaking changes are intentional (plugins, server API, terminal client config) and "supported V1 functionality outside those areas is intended to remain compatible with V1", so this is filed as a compatibility bug.
Project ids for non-git directories are not a plain hash of the path (sha1/md5/sha256 of the directory and of common normalizations do not match), so they cannot be backfilled offline — Project.fromDirectory() has to generate them.
Activity
github-actions commentedon Oct 5, 2026
This issue might be a duplicate of existing issues. Please check:
globalproject.globalsessions become invisible in the project-scoped picker after upgrading to V2.project_id=global, hiding them from the per-directory picker.path=NULLare filtered out of project session lists; this overlaps with the second issue described here.EnglandLobster commentedon Oct 9, 2026
Reproduced on macOS 26.5.2 after upgrading from 1.18.35 to 2.0.25, with no global plugins. All 75 legacy sessions were present in
session_v2, but 41 sessions across two non-Git directories remained underglobal. Reassigning their project and settingpath = ""restored project-scoped listing without changing transcript rows or timestamps.The current v2 branch still has a runtime gap:
Project.resolve()creates a directory-specific project, butpersist()returns early whenproject.vcsis absent. Consequently it never publishesWorktree.Event.Resolved, which is what the Session projector uses to adopt legacy sessions.I have a regression test that fails on current v2 and a focused fix that announces markerless directory resolution with exact-directory adoption. Exact matching matters here: resolving a home directory must not claim legacy sessions in unrelated child directories. This complements #51935's migration-time repair by handling directories when they are opened, including projects already created by affected releases.
EnglandLobster commentedon Oct 15, 2026
Reproduced again on 2.0.29 (Ubuntu 24.04, upgrade path 1.18.34 → 2.0.26 → 2.0.29): of 211 migrated/created sessions, 164 remained under
project_id=globalwhile theirdirectorycolumns pointed at real, mostly non-git directories (~,~/interview_experiences, …). The project-scoped picker listed only the handful that happened to be attributed correctly, which reads as "history gone after upgrade".For anyone hitting this before a fix lands:
POST /api/session/{id}/movewith{"directory": "<the session's own directory>"}is a clean server-side workaround. Verified on 2.0.29 that a move:project_idto the directory-resolved project (no longerglobal),pathto'', matching natively-created V2 sessions,After moving the affected sessions, they reappear in the project-scoped
/sessionslist. Batch sketch:Moved 57/57 cleanly here; only
globalsessions whose directories no longer exist (disposable automation workspaces) were left alone.This is runtime repair rather than migration-time, so it also covers projects already mis-attributed by affected releases — the same population the
Worktree.Event.Resolvedadoption fix targets.rekram1-node commentedon Oct 21, 2026
Same issue as #49827, which has more activity. The fix for the runtime side is #54048. Tracking there.