Skip to content

fix(sqlite-persistence): accept Tauri string migration errors - #1900

Merged
KyleAMathews merged 2 commits into
mainfrom
rfc-1659-ws7-tauri-migration
Sep 27, 2026
Merged

KyleAMathews merged 2 commits into
mainfrom
rfc-1659-ws7-tauri-migration

Conversation

@KyleAMathews

@KyleAMathews KyleAMathews commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

🎯 Changes

Tauri's SQL plugin can reject an ALTER TABLE call with a string. The migration check accepted only Error objects. A duplicate-column result could therefore stop persisted Collection startup instead of completing the migration (#1711).

The migration check now accepts messages from strings and Error objects. It ignores a duplicate-column result only when the message names that migration column. Other failures, such as database is locked, still reject startup.

The Tauri integration test seeds a legacy applied_tx table and converts database errors to strings. It runs the migration through the Tauri driver and checks the new column, legacy data, a committed transaction, and data after reopening the database. The test uses Better SQLite to simulate the Tauri error boundary. It does not run in a native Tauri host.

✅ Checklist

  • I tested the affected packages locally with their complete test suites.

Verification:

  • pnpm --dir packages/db-sqlite-persistence-core exec vitest run --pool-options.threads.maxThreads=2 — 176 checks passed, with no type errors.
  • pnpm --dir packages/tauri-db-sqlite-persistence exec vitest run --pool-options.threads.maxThreads=2 — 61 checks passed, with no type errors.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Closes #1711

Summary by CodeRabbit

  • Bug Fixes
    • Tauri-backed SQLite migrations now recognize duplicate-column errors returned as strings, allowing safe retries when migration columns already exist.
    • Unrelated migration failures, such as a locked database, continue to be reported rather than ignored.
    • Existing transaction data remains intact across migration and database reopening.

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: dff55a9f-3e95-46bc-8b36-41912ef244ed

📥 Commits

Reviewing files that changed from the base of the PR and between 4b9617c and 3eb59ce.

📒 Files selected for processing (3)
  • .changeset/fix-tauri-string-migration-errors.md
  • packages/db-sqlite-persistence-core/src/sqlite-core-adapter.ts
  • packages/tauri-db-sqlite-persistence/tests/tauri-persistence.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The duplicate-column migration guard now recognizes matching string failures as well as Error messages. Tauri persistence tests cover migration success, preserved data after reopening, and propagation of unrelated string failures.

Changes

Tauri SQLite migration handling

Layer / File(s) Summary
Recognize duplicate-column string errors
packages/db-sqlite-persistence-core/src/sqlite-core-adapter.ts, .changeset/fix-tauri-string-migration-errors.md
The guard checks string values and Error messages for the column name and an accepted duplicate-column phrase. The changeset declares patch releases for both packages.
Verify Tauri migration behavior
packages/tauri-db-sqlite-persistence/tests/tauri-persistence.test.ts
Tests cover stringified execution errors during migration, preserved migration and replay data after reopening, and propagation of an unrelated string failure.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 3eb59

The migration test covers startup with an existing column, and unrelated database errors remain visible. No merge-blocking issue was identified.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 3eb59

The migration now accepts a narrowly matched string error so an existing database can start without discarding legacy data. No new data-access path was identified. The regression test uses a simulated database boundary, so native-host behavior and recovery from an interrupted migration remain unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed decision affects initialization of the shared applied_tx schema in a database supplied to the persistence adapter. The evidence does not establish a new remote caller or an expanded privilege boundary.

Trust Boundaries and Controls

  • observed — A database execution error crosses from the Tauri driver into core migration policy without driver-side suppression. Core accepts only the matching duplicate-column message; the unrelated-error test confirms rejection through the adapter.

Resilience and Maintainability Implications

  • observed — The fixture preserves a legacy replay value, commits a later transaction, and reads both after reopening. It simulates stringified errors with Better SQLite rather than exercising a native Tauri host.

Hardening Proposals

  • proposed — If stronger assurance against misleading driver messages is needed, verify the named column’s schema state before treating a string failure as successful migration.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the SQLite persistence fix and the handling of Tauri string migration errors.
Description check ✅ Passed The description explains the change, motivation, test coverage, release impact, changeset, and linked issue. It also records successful verification for both affected packages.
Linked Issues check ✅ Passed The change meets issue [#1711]. isDuplicateColumnAddError now matches both string failures and Error failures. It requires the target column name and a duplicate-column or already-exists message. …
Out of Scope Changes check ✅ Passed The changes stay within issue [#1711]. The adapter change implements string error matching. The Tauri tests verify the migration behavior and unrelated-error rejection. The changeset documents the rel…
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Sep 26, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-db

npm i https://pkg.pr.new/@tanstack/angular-db@1900

@tanstack/browser-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/browser-db-sqlite-persistence@1900

@tanstack/capacitor-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/capacitor-db-sqlite-persistence@1900

@tanstack/cloudflare-durable-objects-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/cloudflare-durable-objects-db-sqlite-persistence@1900

@tanstack/db

npm i https://pkg.pr.new/@tanstack/db@1900

@tanstack/db-ivm

npm i https://pkg.pr.new/@tanstack/db-ivm@1900

@tanstack/db-sqlite-persistence-core

npm i https://pkg.pr.new/@tanstack/db-sqlite-persistence-core@1900

@tanstack/electric-db-collection

npm i https://pkg.pr.new/@tanstack/electric-db-collection@1900

@tanstack/electron-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/electron-db-sqlite-persistence@1900

@tanstack/expo-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/expo-db-sqlite-persistence@1900

@tanstack/node-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/node-db-sqlite-persistence@1900

@tanstack/offline-transactions

npm i https://pkg.pr.new/@tanstack/offline-transactions@1900

@tanstack/powersync-db-collection

npm i https://pkg.pr.new/@tanstack/powersync-db-collection@1900

@tanstack/query-db-collection

npm i https://pkg.pr.new/@tanstack/query-db-collection@1900

@tanstack/react-db

npm i https://pkg.pr.new/@tanstack/react-db@1900

@tanstack/react-native-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/react-native-db-sqlite-persistence@1900

@tanstack/react-router-with-db

npm i https://pkg.pr.new/@tanstack/react-router-with-db@1900

@tanstack/rxdb-db-collection

npm i https://pkg.pr.new/@tanstack/rxdb-db-collection@1900

@tanstack/solid-db

npm i https://pkg.pr.new/@tanstack/solid-db@1900

@tanstack/svelte-db

npm i https://pkg.pr.new/@tanstack/svelte-db@1900

@tanstack/tauri-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/tauri-db-sqlite-persistence@1900

@tanstack/trailbase-db-collection

npm i https://pkg.pr.new/@tanstack/trailbase-db-collection@1900

@tanstack/vue-db

npm i https://pkg.pr.new/@tanstack/vue-db@1900

commit: 3eb59ce

@github-actions

Copy link
Copy Markdown
Contributor

Size Change: 0 B

Total Size: 172 kB

ℹ️ View Unchanged
Filename Size
packages/db/dist/esm/client.js 3.66 kB
packages/db/dist/esm/collection-options.js 236 B
packages/db/dist/esm/collection/change-events.js 1.44 kB
packages/db/dist/esm/collection/changes.js 2.4 kB
packages/db/dist/esm/collection/cleanup-queue.js 794 B
packages/db/dist/esm/collection/events.js 481 B
packages/db/dist/esm/collection/index.js 4.44 kB
packages/db/dist/esm/collection/indexes.js 1.99 kB
packages/db/dist/esm/collection/lifecycle.js 2.69 kB
packages/db/dist/esm/collection/mutations.js 2.61 kB
packages/db/dist/esm/collection/state.js 6.94 kB
packages/db/dist/esm/collection/subscription.js 8.81 kB
packages/db/dist/esm/collection/sync.js 5.03 kB
packages/db/dist/esm/collection/transaction-metadata.js 144 B
packages/db/dist/esm/deferred.js 207 B
packages/db/dist/esm/errors.js 5.34 kB
packages/db/dist/esm/event-emitter.js 964 B
packages/db/dist/esm/index.js 3.82 kB
packages/db/dist/esm/indexes/auto-index.js 829 B
packages/db/dist/esm/indexes/base-index.js 1.14 kB
packages/db/dist/esm/indexes/basic-index.js 2.07 kB
packages/db/dist/esm/indexes/btree-index.js 2.26 kB
packages/db/dist/esm/indexes/index-registry.js 820 B
packages/db/dist/esm/indexes/reverse-index.js 376 B
packages/db/dist/esm/live-query-adapter.js 318 B
packages/db/dist/esm/live-query-observer.js 3.69 kB
packages/db/dist/esm/live-query-options.js 702 B
packages/db/dist/esm/live-query-window-controller.js 4.36 kB
packages/db/dist/esm/local-only.js 989 B
packages/db/dist/esm/local-storage.js 2.17 kB
packages/db/dist/esm/optimistic-action.js 359 B
packages/db/dist/esm/paced-mutations.js 496 B
packages/db/dist/esm/proxy.js 3.32 kB
packages/db/dist/esm/query/builder/clone-query.js 748 B
packages/db/dist/esm/query/builder/functions.js 1.47 kB
packages/db/dist/esm/query/builder/index.js 6.72 kB
packages/db/dist/esm/query/builder/query-ir.js 116 B
packages/db/dist/esm/query/builder/ref-proxy.js 1.28 kB
packages/db/dist/esm/query/compiler/evaluators.js 2.04 kB
packages/db/dist/esm/query/compiler/expressions.js 603 B
packages/db/dist/esm/query/compiler/group-by.js 4.14 kB
packages/db/dist/esm/query/compiler/index.js 9.11 kB
packages/db/dist/esm/query/compiler/joins.js 2.99 kB
packages/db/dist/esm/query/compiler/lazy-targets.js 1.12 kB
packages/db/dist/esm/query/compiler/order-by.js 1.91 kB
packages/db/dist/esm/query/compiler/parent-routes.js 319 B
packages/db/dist/esm/query/compiler/query-equivalence.js 455 B
packages/db/dist/esm/query/compiler/route-metadata.js 1.24 kB
packages/db/dist/esm/query/compiler/select.js 1.59 kB
packages/db/dist/esm/query/effect.js 5.18 kB
packages/db/dist/esm/query/equality-value-identity.js 591 B
packages/db/dist/esm/query/expression-helpers.js 1.43 kB
packages/db/dist/esm/query/ir-stable-identity.js 4.18 kB
packages/db/dist/esm/query/ir.js 1.74 kB
packages/db/dist/esm/query/live-query-collection.js 391 B
packages/db/dist/esm/query/live/bucket-facade-adapter.js 2.73 kB
packages/db/dist/esm/query/live/collection-config-builder.js 7.1 kB
packages/db/dist/esm/query/live/collection-registry.js 264 B
packages/db/dist/esm/query/live/collection-subscriber.js 2.29 kB
packages/db/dist/esm/query/live/internal.js 145 B
packages/db/dist/esm/query/live/materialized-pipeline.js 2.32 kB
packages/db/dist/esm/query/live/ordered-source-loader.js 4.32 kB
packages/db/dist/esm/query/live/subset-demand-controller.js 1.26 kB
packages/db/dist/esm/query/live/utils.js 1.14 kB
packages/db/dist/esm/query/optimizer.js 3.11 kB
packages/db/dist/esm/query/query-once.js 359 B
packages/db/dist/esm/query/runtime-reference-identity.js 572 B
packages/db/dist/esm/query/subset-dedupe.js 497 B
packages/db/dist/esm/scheduler.js 1.34 kB
packages/db/dist/esm/SortedMap.js 1.3 kB
packages/db/dist/esm/strategies/debounceStrategy.js 247 B
packages/db/dist/esm/strategies/queueStrategy.js 428 B
packages/db/dist/esm/strategies/throttleStrategy.js 246 B
packages/db/dist/esm/sync-persistence.js 530 B
packages/db/dist/esm/transactions.js 3.71 kB
packages/db/dist/esm/utils.js 1.21 kB
packages/db/dist/esm/utils/array-utils.js 270 B
packages/db/dist/esm/utils/browser-polyfills.js 304 B
packages/db/dist/esm/utils/btree.js 4.51 kB
packages/db/dist/esm/utils/callbacks.js 174 B
packages/db/dist/esm/utils/comparison.js 1.49 kB
packages/db/dist/esm/utils/cursor.js 677 B
packages/db/dist/esm/utils/error.js 167 B
packages/db/dist/esm/utils/get-or-create.js 155 B
packages/db/dist/esm/utils/index-optimization.js 2.42 kB
packages/db/dist/esm/utils/type-guards.js 230 B
packages/db/dist/esm/utils/uuid.js 449 B
packages/db/dist/esm/virtual-props.js 360 B

compressed-size-action::db-package-size

@github-actions

Copy link
Copy Markdown
Contributor

Size Change: 0 B

Total Size: 7.34 kB

ℹ️ View Unchanged
Filename Size
packages/react-db/dist/esm/DbProvider.js 317 B
packages/react-db/dist/esm/HydrationBoundary.js 263 B
packages/react-db/dist/esm/index.js 330 B
packages/react-db/dist/esm/live-query-internals.js 282 B
packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.9 kB
packages/react-db/dist/esm/useLiveQuery.js 2.68 kB
packages/react-db/dist/esm/useLiveQueryEffect.js 355 B
packages/react-db/dist/esm/useLiveSuspenseQuery.js 812 B
packages/react-db/dist/esm/usePacedMutations.js 401 B

compressed-size-action::react-db-package-size

@KyleAMathews
KyleAMathews merged commit f473a36 into main Sep 27, 2026
11 checks passed
@KyleAMathews
KyleAMathews deleted the rfc-1659-ws7-tauri-migration branch September 27, 2026 12:23
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.

Tauri: persisted collection startup fails with duplicate column name: replay_json

1 participant