-
Notifications
You must be signed in to change notification settings - Fork 12.1k
Description
Description
OpenCode v1.2.21 — Session Migration Fix
Problem
After upgrading to OpenCode v1.2.21, previous sessions disappear from the TUI session list.
Root Cause
v1.2.21 changed how projects are identified:
| Version | project_id | How it works |
|---|---|---|
| <= 1.2.20 | "global" |
All directories share one project |
| >= 1.2.21 | <git root commit SHA> |
Each git repo gets a unique ID based on its first commit |
The upgrade creates a new project entry with the git-derived ID, but the built-in migrateFromGlobal() function may fail to reassign existing sessions. Result: 0 sessions visible.
For non-git directories, the global project's worktree changed from the actual path to "/", so sessions stored with the real directory path no longer match.
Diagnosis
1. Locate the database
~/.local/share/opencode/opencode.db
2. Find the new project ID
# Option A: read from git cache
cat .git/opencode
# Option B: compute it yourself (run from the repo)
git rev-list --max-parents=0 --all | sort | head -13. Check for orphaned sessions
bun -e "
const { Database } = require('bun:sqlite');
const d = new Database('$HOME/.local/share/opencode/opencode.db', {readonly: true});
// All sessions grouped by project_id and directory
const rows = d.query('SELECT project_id, directory, COUNT(*) as c FROM session GROUP BY project_id, directory ORDER BY c DESC').all();
rows.forEach(r => console.log(r.project_id, '|', r.directory, '|', r.c, 'sessions'));
"If you see sessions under project_id = 'global' with a real directory path, they're orphaned.
Fix
Close OpenCode before running these.
Case 1: Git-enabled directory
Sessions are under global but should be under the git root commit SHA.
bun -e "
const { Database } = require('bun:sqlite');
const d = new Database('$HOME/.local/share/opencode/opencode.db');
const PROJECT_ID = '<git-root-commit-sha>'; // from: git rev-list --max-parents=0 --all
const DIRECTORY = '<your-project-path>'; // e.g. /home/user/my-project
const before = d.query(\`SELECT COUNT(*) as c FROM session WHERE project_id = 'global' AND directory = '\${DIRECTORY}'\`).get();
console.log('Sessions to migrate:', before.c);
d.run(\`UPDATE session SET project_id = '\${PROJECT_ID}' WHERE project_id = 'global' AND directory = '\${DIRECTORY}'\`);
const after = d.query(\`SELECT COUNT(*) as c FROM session WHERE project_id = '\${PROJECT_ID}'\`).get();
console.log('Sessions under new project_id:', after.c);
d.close();
"Case 2: Non-git directory
Sessions have the real directory path but the global project now expects "/".
bun -e "
const { Database } = require('bun:sqlite');
const d = new Database('$HOME/.local/share/opencode/opencode.db');
const DIRECTORY = '<your-directory-path>'; // e.g. /home/user/notes
const before = d.query(\`SELECT COUNT(*) as c FROM session WHERE project_id = 'global' AND directory = '\${DIRECTORY}'\`).get();
console.log('Sessions to fix:', before.c);
d.run(\`UPDATE session SET directory = '/' WHERE project_id = 'global' AND directory = '\${DIRECTORY}'\`);
console.log('Fixed. Sessions now accessible under global project.');
d.close();
"Verification
bun -e "
const { Database } = require('bun:sqlite');
const d = new Database('$HOME/.local/share/opencode/opencode.db', {readonly: true});
const orphans = d.query(\"SELECT project_id, directory, COUNT(*) as c FROM session WHERE project_id = 'global' AND directory != '/' GROUP BY project_id, directory\").all();
if (orphans.length === 0) {
console.log('No orphaned sessions. All good.');
} else {
console.log('Remaining orphans:');
orphans.forEach(o => console.log(o.directory, ':', o.c, 'sessions'));
}
d.close();
"Notes
- Child sessions (subagent tasks) have a
parent_idset — the TUI only shows top-level sessions, so the count may look lower than expected - The
.git/opencodefile caches the project ID so it doesn't rungit rev-liston every startup - If a repo has multiple root commits (e.g. after a
--allow-unrelated-historiesmerge), opencode sorts them and picks the first - No
sqlite3needed —bun:sqliteis built into bun
Upstream References
- PR #16389 — fix for project ID cache and worktree session loss (open)
- Issue #16506 — Drizzle migration name mismatch crash on v1.2.21
- Issue #15719 — non-git directory shows
"/"as project - Source:
packages/opencode/src/project/project.ts—migrateFromGlobal()andfromDirectory()
Plugins
OmO
OpenCode version
1.2.21
Steps to reproduce
After upgrading to 1.2.1 all sessions disappear from TUI. Even the global ones with no git.
Screenshot and/or share link
No response
Operating System
Ubuntu 24.04 inside WSL2
Terminal
Windows Terminal