Skip to content

fix(core): serialize concurrent database migrations - #13067

Merged
johnnyeric merged 1 commit into
mainfrom
johnnyeric/fix-migration-race
Aug 11, 2026
Merged

fix(core): serialize concurrent database migrations#13067
johnnyeric merged 1 commit into
mainfrom
johnnyeric/fix-migration-race

Conversation

@johnnyeric

@johnnyeric johnnyeric commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Issue

Fixes #13060

Context

Kilo 7.4.21 can crash during startup when two processes share the same SQLite database and attempt the same pending migration. applyOnly() previously took one completed-migration snapshot, so a second process could record an ID after that snapshot; the first process would replay the migration and then fail its journal insert with UNIQUE constraint failed: migration.id.

Implementation

Run each pending migration in a BEGIN IMMEDIATE transaction and re-check that migration's journal ID after acquiring the SQLite write reservation. If another process already recorded it, skip up(); otherwise apply the migration and journal it atomically.

The regression coverage verifies both the stale-snapshot skip and that the write reservation is held before migration work begins. A patch changeset documents the user-facing startup fix.

Screenshots / Video

N/A

How to Test

Manual/local verification

  • Agent reproduced the original two-process race against the pre-fix implementation: the losing process failed on the migration journal INSERT with SQLITE_CONSTRAINT_PRIMARYKEY / UNIQUE constraint failed: migration.id.
  • Agent repeated the same schedule with this fix: both processes completed, the journal contained one row for the migration, and the migration state was correct.
  • Agent ran cd packages/core && bun test test/kilocode/database-migration-compat.test.ts test/database-migration.test.ts (21 passed, 0 failed).
  • Agent ran cd packages/core && bun run typecheck.
  • Agent ran bun run script/check-opencode-annotations.ts --worktree.
  • Agent ran git diff --check.
  • The repository pre-push hook ran bun turbo typecheck --filter=!@kilocode/kilo-jetbrains successfully.

Reviewer test steps

  1. Run cd packages/core.
  2. Run bun test test/kilocode/database-migration-compat.test.ts test/database-migration.test.ts.
  3. Confirm the compatibility tests verify that an ID recorded after the initial snapshot skips replay and that a second SQLite writer receives SQLITE_BUSY while the migration transaction holds its immediate write reservation.

Checklist

  • Issue linked above, or exception explained
  • Tests/verification described
  • Screenshots/video included for visual changes, or marked N/A
  • Changeset considered for user-facing changes
  • I personally reviewed the diff and can explain the changes, including any AI-assisted work.

@johnnyeric
johnnyeric marked this pull request as ready for review August 11, 2026 12:39
@kilo-code-bot

kilo-code-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • .changeset/steady-migration-journal.md
  • packages/core/src/database/migration.ts
  • packages/core/test/kilocode/database-migration-compat.test.ts

The fix is sound: db.transaction(tx, { behavior: "immediate" }) issues BEGIN IMMEDIATE via the Effect drizzle session, so the journal re-check runs after the SQLite write reservation is acquired — closing the stale-snapshot race where a second process records the migration ID before the first replays it. Production sets busy_timeout = 5000 before migrations run, so a concurrent starter waits for the winner rather than crashing. Tests exercise the real implementation (no mocks), cover both the skip and lock-pinning paths, and clean up the extra SQLite connection. Changeset correctly targets @kilocode/cli with a user-facing description.

@johnnyeric
johnnyeric merged commit 2c2b0a2 into main Aug 11, 2026
39 of 43 checks passed
@johnnyeric
johnnyeric deleted the johnnyeric/fix-migration-race branch August 11, 2026 14:26
@jazir555

jazir555 commented Aug 11, 2026

Copy link
Copy Markdown

Since this fixes the issue, will the database corruption be fixed when this lands in a kilo update? My existing database got corrupted due to this issue.

@johnnyeric

Copy link
Copy Markdown
Contributor Author

Yes. The next release containing this fix should open your existing database normally if this issue caused the startup failure. The error message you shared does not indicate that the database was corrupted. If you encounter any other errors after updating, please let us know and include the complete error message.

t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server Connection Error - unexpected error

3 participants