fix(opencode): private session DB per worker — concurrent workers were dying at "database is locked" - #79
Open
jeffhamons wants to merge 2 commits into
Conversation
OpenCode keeps its session store at $XDG_DATA_HOME/opencode/opencode.db, defaulting to ~/.local/share/opencode -- one file, shared by every worker, opened for write, growing without bound. On 2026-07-27 it stood at 1.78 GB and two of three concurrently-launched workers died before their first tool call with "database is locked", recorded as model failures though no model had run. Because every non-Codex model routes through this engine, the contention penalises exactly the cheap tier, and worsens with parallelism. Point XDG_DATA_HOME at a per-run directory under the existing scratch root so each worker gets a private store. Credentials live beside the DB, so seed the fresh root by COPYING auth.json -- never symlinking, since the Seatbelt profile denies writes outside SCRATCH and a symlink would resolve straight back to the shared file this exists to avoid. Also add OC_BASE ($HOME/.opencode) to the profile's allowed subpaths, and note on the --no-sandbox path that it still shares the global DB: fine for a lone full-access task, not for a fan-out.
tests/test_contributors.py audits every author in the branch history against `## Contributors`, so any first-time contributor's PR is red until the line lands. Adding it here rather than leaving a red required check for you to interpret. Identical text on both my open PRs (NateBJones-Projects#79, NateBJones-Projects#80) so the second resolves trivially once the first merges — drop the commit if you would rather add credit at merge time.
jeffhamons
added a commit
to jeffhamons/ringer
that referenced
this pull request
Jul 27, 2026
tests/test_contributors.py audits every author in the branch history against `## Contributors`, so any first-time contributor's PR is red until the line lands. Adding it here rather than leaving a red required check for you to interpret. Identical text on both my open PRs (NateBJones-Projects#79, NateBJones-Projects#80) so the second resolves trivially once the first merges — drop the commit if you would rather add credit at merge time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fan three OpenCode workers out at once on this machine and two of them die at
rc=1before the model produces a token:OpenCode keeps its session store at
$XDG_DATA_HOME/opencode/opencode.db, defaulting to~/.local/share/opencode— one file, shared by every worker, opened for write, growing without bound. On 2026-07-27 mine stood at 1.78 GB, and the workers that lost the lock race were logged as ordinary model failures though no model had run.The part that made this worth chasing: every non-Codex model routes through this engine, so the contention penalises exactly the cheap tier — the models you fan out widest — and it worsens as parallelism rises. It reads on the scoreboard as "the cheap lane can not cope." That is a surface misstating what happened, which is the bug class this project treats as unforgivable.
The fix
Point
XDG_DATA_HOMEat a per-run directory under the scratch root the wrapper already creates and tears down, so each worker gets a private store. Two details that are load-bearing:auth.jsonby copying, never symlinking — the Seatbelt profile denies writes outsideSCRATCH, and a symlink would resolve straight back to the shared file this exists to avoid.OC_BASE($HOME/.opencode) is added to the profile subpaths.The
--no-sandboxpath deliberately keeps the shared DB and now says so in a comment: fine for a lone full-access task, not for a fan-out.Proof
Full suite on macOS (Python 3.14), this branch rebased on current
main(2c2b599): 218 of 218 pass.tests/test_contributors.pyinitially failed — I have no merged work yet, so the credit audit named me. A second commit adds the README line; drop that commit if you would rather add credit at merge time.Adjacent work
#67 adds
engines/opencode-sandboxed-linux.sh. That wrapper will want the same treatment — happy to mirror it here or in a follow-up, whichever you prefer for review size.Update: the README credit line is now a second commit on this branch, so the suite is fully green. The same line is on #79 and #80 — identical text, so whichever merges second resolves trivially. Drop the commit if you would rather handle credit yourself.