Skip to content

fix: scope database connections to their NitroSQLite owner - #421

Merged
chrispader merged 3 commits into
mainfrom
codex/fix-runtime-connection-ownership
Oct 1, 2026
Merged

chrispader merged 3 commits into
mainfrom
codex/fix-runtime-connection-ownership

Conversation

@chrispader

@chrispader chrispader commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

NitroSQLite keeps database connections in a process-wide registry after their JavaScript runtime is destroyed. A replacement runtime then fails to reopen the same database with an "already open" error, which prevents Onyx from loading the persisted session in the Expensify deploy blocker. This change makes each native NitroSQLite root own its default and independent connections and close them on destruction.

Queries, batches, file imports, and prepared statements resolve through their owning root. Pending work retains its original connection and fails after closure. A newer root can open the same database name, and delayed cleanup from an older root cannot close its handles. Weak references preserve the existing migration and deletion safeguards across overlapping roots without keeping old connections alive.

The grouped-batch tests added on main exposed an empty-array conversion error during integration. The native converter now skips an empty flat parameter array as well as an empty nested group, preserving the behavior those tests require. This correction is separate from the ownership backports for 9.8.3 and 10.0.1.

The connection regression tests cover owner destruction, retained handles, overlapping owners, WAL persistence, unfinished transaction rollback, and 100 reopen cycles. A separate native lifecycle check fails on unmodified main with the repeat-open error and passes with this fix, including stale async work and prepared statements. That check uses the real implementation and bundled SQLite with binding-only shims and a deferred scheduler.

Reproduction

  1. Open a database in a React Native runtime and write committed data.
  2. Destroy that runtime while keeping the native process alive.
  3. Create a new runtime and reopen the same database. It should open and read the committed data.

For Expensify, repeat New Expensify to Classic to New Expensify transitions, with and without reset, and verify the session and offline data survive. The full Expensify Android staging flow and iOS runtime teardown remain unverified. Expensify needs a dependency update and native rebuild to consume this fix.

@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
react-native-nitro-sqlite Ready Ready Preview Oct 1, 2026 9:48am UTC

Request Review

@chrispader
chrispader merged commit 6dd1049 into main Oct 1, 2026
14 of 15 checks passed

This branch was successfully deployed

1 active deployment
Preview — 4ba0c6cf Deployed Oct 1, 2026 by vercel[bot]
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.

1 participant