JSON→SQLite session migration silently skips for incremental upgrades #9357

Open
opened 2026-02-16 18:12:16 -05:00 by yindo · 1 comment
Owner

Originally created by @dylan-conlin on GitHub (Feb 14, 2026).

Originally assigned to: @rekram1-node on GitHub.

Bug

The one-time JSON→SQLite session migration gate (json-migration.ts) checks whether opencode.db exists to decide whether to run. But opencode.db can exist from earlier schema migrations (e.g., Jan 27) that predate the session migration commit (6d95f0d14, Feb 13).

For any user who updated incrementally (rather than fresh install), the migration is silently skipped and all pre-existing JSON session files are permanently orphaned — they exist on disk but are invisible to the current SQLite-based session code.

Reproduction

  1. Have an OpenCode installation that created opencode.db before commit 6d95f0d14 (any user who ran a version between late Jan and Feb 13)
  2. Update to a version including 6d95f0d14
  3. Start OpenCode — migration is skipped because DB already exists
  4. All JSON sessions under ~/.local/share/opencode/storage/session/ are now orphaned

Evidence

-- DB was created Jan 27, migration commit is Feb 13
sqlite3 ~/.local/share/opencode/opencode.db \
  "SELECT *, datetime(created_at/1000, 'unixepoch', 'localtime') FROM __drizzle_migrations ORDER BY created_at;"
-- → 2026-01-27 14:23 (first migration, DB created)
-- → 2026-02-13 06:41 (third migration, same release window as session migration)
# 188 JSON session files on disk, never imported
find ~/.local/share/opencode/storage/session -name "*.json" | wc -l
# → 188

Root Cause

packages/opencode/src/storage/index.ts:82-83:

const marker = path.join(Global.Path.data, "opencode.db")
if (!(await Bun.file(marker).exists())) { /* run json migration */ }

The gate assumes "DB exists = sessions already migrated." But the DB can exist from earlier schema migrations that had nothing to do with session storage.

Suggested Fix

Replace the opencode.db existence check with a dedicated migration marker (e.g., a flag in a migrations table, or a .json-migration-complete marker file). This allows the JSON import to run even when the DB already exists from prior schemas.

Originally created by @dylan-conlin on GitHub (Feb 14, 2026). Originally assigned to: @rekram1-node on GitHub. ## Bug The one-time JSON→SQLite session migration gate (`json-migration.ts`) checks whether `opencode.db` exists to decide whether to run. But `opencode.db` can exist from earlier schema migrations (e.g., Jan 27) that predate the session migration commit (`6d95f0d14`, Feb 13). For any user who updated incrementally (rather than fresh install), the migration is silently skipped and all pre-existing JSON session files are permanently orphaned — they exist on disk but are invisible to the current SQLite-based session code. ## Reproduction 1. Have an OpenCode installation that created `opencode.db` before commit `6d95f0d14` (any user who ran a version between late Jan and Feb 13) 2. Update to a version including `6d95f0d14` 3. Start OpenCode — migration is skipped because DB already exists 4. All JSON sessions under `~/.local/share/opencode/storage/session/` are now orphaned ## Evidence ```sql -- DB was created Jan 27, migration commit is Feb 13 sqlite3 ~/.local/share/opencode/opencode.db \ "SELECT *, datetime(created_at/1000, 'unixepoch', 'localtime') FROM __drizzle_migrations ORDER BY created_at;" -- → 2026-01-27 14:23 (first migration, DB created) -- → 2026-02-13 06:41 (third migration, same release window as session migration) ``` ```bash # 188 JSON session files on disk, never imported find ~/.local/share/opencode/storage/session -name "*.json" | wc -l # → 188 ``` ## Root Cause `packages/opencode/src/storage/index.ts:82-83`: ```typescript const marker = path.join(Global.Path.data, "opencode.db") if (!(await Bun.file(marker).exists())) { /* run json migration */ } ``` The gate assumes "DB exists = sessions already migrated." But the DB can exist from earlier schema migrations that had nothing to do with session storage. ## Suggested Fix Replace the `opencode.db` existence check with a dedicated migration marker (e.g., a flag in a migrations table, or a `.json-migration-complete` marker file). This allows the JSON import to run even when the DB already exists from prior schemas.
Author
Owner

@github-actions[bot] commented on GitHub (Feb 14, 2026):

This issue might be related to other session storage issues. Please also check:

  • #13611: Session JSON→SQLite migration running in non-interactive mode (opencode serve)
  • #12889: NotFoundError when launching desktop app with missing session files
  • #10904: Sessions existing on disk but unavailable after system crash

These are distinct issues but may benefit from shared context around session persistence and migration logic.

@github-actions[bot] commented on GitHub (Feb 14, 2026): This issue might be related to other session storage issues. Please also check: - #13611: Session JSON→SQLite migration running in non-interactive mode (`opencode serve`) - #12889: NotFoundError when launching desktop app with missing session files - #10904: Sessions existing on disk but unavailable after system crash These are distinct issues but may benefit from shared context around session persistence and migration logic.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#9357