Repository navigation
Description
Summary
The V1→V2 session data migration aborts every time it reaches a V1 session whose part rows contain large inline base64 attachments, leaving the whole pre-upgrade session list empty. The resident background service then repeats the failure on every boot and never advances its resume cursor.
Environment
- opencode version: 2.2.5 (channel: latest)
- OS: Linux 6.18.13-arch1-1 (Arch, x64)
- Terminal: xterm-256color (foot)
- Shell: bash
- Install/channel: official bun build via mise (
mise installs/opencode/2.2.5) - Active plugins (loaded at runtime): oh-my-openagent@latest, opencode-antigravity-auth@latest, opencode-chrome-annotation@latest
Reproduction
- Have a V1 database (from 1.x) with a session whose
partcontains adata:application/pdf;base64,...inline attachment of a few hundred MB. In my case one assistant message held threefileparts: 530 MB, 283 MB and 83 MB of base64 in theirurlfields (~900 MB total). - Upgrade to 2.2.5 and boot the shared service. Schema migrations complete; the background
migration.v1-v2data migration starts. - Wait about 10 seconds.
Expected Behavior
The migration should either complete, or skip an oversized session with a recorded warning and keep going. The resume cursor (kv key migration.v1-v2) should advance each boot so progress converges.
Actual Behavior
The migration dies before any user-visible error, with this in the server log:
level=ERROR role=server message="V1 migration failed" cause="Cause([Die(RangeError: Out of memory)])"
Observed five times across five service restarts, always at the same state:
kv['migration.v1-v2']stayed frozen at{"phase":"sessions","cursor":"<last ok session id>"}- it never flipped tocompleted.SELECT COUNT(*) FROM session_v2stayed at 21 whilesessionheld 501 rows.- The session picker showed only the sessions migrated before the first failure (plus newly created ones). Everything older was invisible across every project.
- Available system memory was ~5.6 GB of 15 GB plus unused swap, so this is an allocation limit, not real RAM exhaustion. Loading one 530 MB base64 string plus its JSON structure into JS objects is enough to trip
RangeError: Out of memory.
The failing session is always the next V1 session below the frozen cursor: the loop picks SELECT ... FROM session WHERE id < :cursor ORDER BY id DESC LIMIT 1, loads all of that session's message and part rows and their JSON payloads into memory in one go, and dies there. As long as the next session contains an inline mega-attachment, the migration can never pass it.
Workaround (verified)
Advance the resume cursor past the offending session so the loop starts below it:
sqlite3 "$HOME/.local/share/opencode/opencode.db" \
"UPDATE kv SET value=json_set(value,'$.cursor','<offending-session-id>') WHERE key='migration.v1-v2';"
opencode service restartAfter that the migration resumed and completed ({"phase":"completed"}, all remaining sessions imported). Secondary fix that reclaimed ~1.8 GB: strip the base64 url in the offending part rows with a small script and VACUUM (dB shrank from 2.3 GB to 559 MB).
Suggestion: a size guard - either stream per-part conversion instead of materializing all rows of a session, or skip sessions above a threshold with the same warnings channel already used for invalid rows (Skipped V1 migration row), and note the skip in the migration state so users can be told which session was left behind.
Additional Context
- Frequency: 100% reproducible per boot until the cursor is advanced past the bad session.
- The offending attachment had been pasted into chat months earlier (Aug 2026); the session itself had been used normally since.
- Worked from plain sqlite inspection of
opencode.db; no exotic config involved. Plugin list present from config defaults, not plugin-specific.
Activity
opencodejr commentedon Nov 5, 2026
Thanks for the detailed report and the verified workaround!
I think this is a duplicate of #50076. That issue reports the same
V1 migration failed/RangeError: Out of memoryon a session with a large inline base64 PDF, with themigration.v1-v2cursor stuck and the same failure on every restart.Possible duplicates and related issues, ordered by likelihood:
/movesilently does nothing when a V1 inline-PDF part fails to decodeopencode.dbYour report adds useful information to #50076. A Linux reproduction attempt there couldn't trigger the OOM and guessed it might only affect macOS. Your case is on Linux x64 with 2.2.5, with about 900 MB across three
fileparts in a single message, so total session size may be what matters. Please consider adding these details to #50076.The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
0xAlok commentedon Nov 5, 2026
Confirmed duplicate of #50076. Cross-posted the Linux x64 reproduction details and the verified cursor workaround there (they correct the macOS-only hypothesis in that report). Closing this one as such.
opencodejr commentedon Nov 5, 2026
Thanks for confirming, and for adding the Linux x64 reproduction and the cursor workaround to #50076. Further updates on this will be tracked there.
opencodejr commentedon Nov 6, 2026
Closing this as a duplicate of #50076, as you confirmed. Thanks again for adding the Linux x64 reproduction and the cursor workaround there. Please follow #50076 for any updates on the V1→V2 migration running out of memory on large inline attachments.