Skip to content

Comments

Add runtime validation for collection config with helpful error messages#1278

Open
KyleAMathews wants to merge 3 commits intomainfrom
claude/improve-error-messages-2xo72
Open

Add runtime validation for collection config with helpful error messages#1278
KyleAMathews wants to merge 3 commits intomainfrom
claude/improve-error-messages-2xo72

Conversation

@KyleAMathews
Copy link
Collaborator

🎯 Changes

This PR adds comprehensive runtime validation for the createCollection configuration to catch common misconfiguration mistakes early with clear, actionable error messages.

Key additions:

  1. New validation module (validate-config.ts): Validates collection config at runtime before passing to CollectionImpl, checking:

    • Config is a valid object (not null, string, or array)
    • Required getKey function is present and is a function
    • Required sync config is present, is an object, and contains a sync function
    • Optional callback options (onInsert, onUpdate, onDelete, compare) are functions if provided
    • Optional properties have correct types (id as string, gcTime as number, startSync as boolean, etc.)
    • Enum-like properties have valid values (autoIndex: "off"/"eager", syncMode: "eager"/"on-demand")
    • Unknown properties are detected with typo suggestions using Levenshtein distance
  2. New error classes in errors.ts:

    • CollectionRequiresGetKeyError
    • InvalidGetKeyError
    • InvalidSyncConfigError
    • InvalidSyncFunctionError
    • InvalidCallbackOptionError
    • InvalidOptionTypeError
    • UnknownCollectionConfigError (with typo suggestions and valid property list)
  3. Integration: createCollection now calls validateCollectionConfig before creating the collection instance

  4. Comprehensive test suite (collection-config-validation.test.ts): 400+ lines of tests covering all validation scenarios, error messages, typo detection, and valid configurations

Benefits:

  • Better DX: Clear error messages instead of cryptic TypeScript or runtime errors
  • Typo detection: Suggests correct property names for common typos (e.g., "getkey" → "getKey")
  • Early feedback: Catches configuration errors immediately at collection creation time
  • Helpful examples: Error messages include usage examples for common mistakes

✅ Checklist

  • I have tested this code locally with pnpm test.

🚀 Release Impact

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

Note: This is a dev-time improvement that adds validation to catch configuration errors earlier. The validation runs at collection creation time but doesn't change the public API or behavior of correctly-configured collections.

https://claude.ai/code/session_01SoqPVFMvsgwf2ciuSU1wRF

…ble error messages

TypeScript errors from createCollection's 8 overloads with deeply nested
generics are extremely hard to read. This adds comprehensive runtime
validation that catches common misconfigurations with clear, actionable
error messages including examples and typo suggestions.

Validations added:
- Missing or wrong-type getKey (must be a function)
- Missing or wrong-type sync config (must be object with sync function)
- Wrong-type callback options (onInsert, onUpdate, onDelete, compare)
- Wrong-type scalar options (id, gcTime, startSync, autoIndex, syncMode, utils)
- Unknown config properties with Levenshtein-based "did you mean?" suggestions

Also fixes:
- localStorageCollectionOptions leaking `parser` property into CollectionConfig
- Test utility mockSyncCollectionOptions leaking `initialData` into CollectionConfig

https://claude.ai/code/session_01SoqPVFMvsgwf2ciuSU1wRF
Wrap validateCollectionConfig() in a process.env.NODE_ENV check so
bundlers can tree-shake the validation code (including Levenshtein
distance, error classes, etc.) in production builds.

https://claude.ai/code/session_01SoqPVFMvsgwf2ciuSU1wRF
@changeset-bot
Copy link

changeset-bot bot commented Feb 19, 2026

⚠️ No Changeset found

Latest commit: ce5038b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 19, 2026

More templates

@tanstack/angular-db

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

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/electric-db-collection

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

@tanstack/offline-transactions

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

@tanstack/powersync-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: ce5038b

@github-actions
Copy link
Contributor

Size Change: +1.86 kB (+2.02%)

Total Size: 93.9 kB

Filename Size Change
./packages/db/dist/esm/collection/index.js 3.39 kB +65 B (+1.96%)
./packages/db/dist/esm/collection/validate-config.js 1.19 kB +1.19 kB (new file) 🆕
./packages/db/dist/esm/errors.js 5.21 kB +513 B (+10.93%) ⚠️
./packages/db/dist/esm/index.js 2.77 kB +80 B (+2.97%)
./packages/db/dist/esm/local-storage.js 2.11 kB +8 B (+0.38%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 1.39 kB
./packages/db/dist/esm/collection/changes.js 1.22 kB
./packages/db/dist/esm/collection/events.js 388 B
./packages/db/dist/esm/collection/indexes.js 1.1 kB
./packages/db/dist/esm/collection/lifecycle.js 1.75 kB
./packages/db/dist/esm/collection/mutations.js 2.34 kB
./packages/db/dist/esm/collection/state.js 3.49 kB
./packages/db/dist/esm/collection/subscription.js 3.71 kB
./packages/db/dist/esm/collection/sync.js 2.41 kB
./packages/db/dist/esm/deferred.js 207 B
./packages/db/dist/esm/event-emitter.js 748 B
./packages/db/dist/esm/indexes/auto-index.js 742 B
./packages/db/dist/esm/indexes/base-index.js 766 B
./packages/db/dist/esm/indexes/btree-index.js 2.17 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.1 kB
./packages/db/dist/esm/indexes/reverse-index.js 538 B
./packages/db/dist/esm/local-only.js 808 B
./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.75 kB
./packages/db/dist/esm/query/builder/functions.js 733 B
./packages/db/dist/esm/query/builder/index.js 4.09 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 1.05 kB
./packages/db/dist/esm/query/compiler/evaluators.js 1.43 kB
./packages/db/dist/esm/query/compiler/expressions.js 430 B
./packages/db/dist/esm/query/compiler/group-by.js 1.81 kB
./packages/db/dist/esm/query/compiler/index.js 2.02 kB
./packages/db/dist/esm/query/compiler/joins.js 2.11 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.45 kB
./packages/db/dist/esm/query/compiler/select.js 1.06 kB
./packages/db/dist/esm/query/expression-helpers.js 1.43 kB
./packages/db/dist/esm/query/ir.js 673 B
./packages/db/dist/esm/query/live-query-collection.js 360 B
./packages/db/dist/esm/query/live/collection-config-builder.js 5.44 kB
./packages/db/dist/esm/query/live/collection-registry.js 264 B
./packages/db/dist/esm/query/live/collection-subscriber.js 2.42 kB
./packages/db/dist/esm/query/live/internal.js 145 B
./packages/db/dist/esm/query/optimizer.js 2.62 kB
./packages/db/dist/esm/query/predicate-utils.js 2.97 kB
./packages/db/dist/esm/query/subset-dedupe.js 921 B
./packages/db/dist/esm/scheduler.js 1.3 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/transactions.js 2.9 kB
./packages/db/dist/esm/utils.js 924 B
./packages/db/dist/esm/utils/browser-polyfills.js 304 B
./packages/db/dist/esm/utils/btree.js 5.61 kB
./packages/db/dist/esm/utils/comparison.js 952 B
./packages/db/dist/esm/utils/cursor.js 457 B
./packages/db/dist/esm/utils/index-optimization.js 1.51 kB
./packages/db/dist/esm/utils/type-guards.js 157 B

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

@github-actions
Copy link
Contributor

Size Change: 0 B

Total Size: 3.7 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 225 B
./packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.17 kB
./packages/react-db/dist/esm/useLiveQuery.js 1.34 kB
./packages/react-db/dist/esm/useLiveSuspenseQuery.js 559 B
./packages/react-db/dist/esm/usePacedMutations.js 401 B

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

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.

2 participants