fix(core): don't first-time enable FTS from syncSearchState#595
fix(core): don't first-time enable FTS from syncSearchState#595
Conversation
syncSearchState (added in 0a61ef4) called enableSearch() when FTS wasn't yet active, triggering FTS5 operations during field creation in the seed. This crashes playground initialization — the seed's explicit enableSearch step handles failures gracefully with a try/catch, but the createField code path didn't. Now syncSearchState only rebuilds an already-active FTS index or disables one that should be off. First-time enablement stays with the seed's try-caught enableSearch call.
🦋 Changeset detectedLatest commit: 04c8b49 The changes in this PR will be included in the next version bump. This PR includes changesets to release 9 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-playground | 04c8b49 | Apr 16 2026, 07:26 AM |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/blocks
@emdash-cms/cloudflare
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
There was a problem hiding this comment.
Pull request overview
Fixes a regression where SchemaRegistry.syncSearchState() could first-time enable FTS during schema mutations (e.g., field creation during seed), causing unhandled FTS failures to crash playground initialization. This keeps first-time enablement in explicitly try/caught flows (seed + admin toggle) while still maintaining already-enabled indexes.
Changes:
- Update
syncSearchState()to only rebuild an already-enabled FTS index when searchable fields change. - Update
syncSearchState()to disable FTS only when it is currently active and search support is removed / no searchable fields remain.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (wantsSearch && searchableFields.length > 0 && ftsActive) { | ||
| await ftsManager.rebuildIndex(collectionSlug, searchableFields, config?.weights); | ||
| } else if (ftsActive && (!wantsSearch || searchableFields.length === 0)) { |
There was a problem hiding this comment.
syncSearchState() no longer enables search when supports includes "search" but FTS isn’t active. The docblock above this function (and several existing unit tests) still describe the old "enable or rebuild" behavior, which will now be incorrect and likely cause failing/incorrect tests and developer confusion. Please update the documentation and adjust tests to reflect the new contract (only rebuild/disable; first-time enable handled elsewhere).
| if (wantsSearch && searchableFields.length > 0 && ftsActive) { | ||
| await ftsManager.rebuildIndex(collectionSlug, searchableFields, config?.weights); | ||
| } else if (ftsActive && (!wantsSearch || searchableFields.length === 0)) { | ||
| await ftsManager.disableSearch(collectionSlug); | ||
| } |
There was a problem hiding this comment.
This change intentionally stops first-time FTS enablement in syncSearchState(), but the repository’s current unit tests assert that creating a searchable field or toggling supports: ["search"] auto-creates the FTS table. As-is, this PR will require updating those tests (and ideally adding a test that verifies "no first-time enable" behavior) to keep CI green and to lock in the new intended behavior.
Tests now explicitly call enableSearch() to set up FTS state before testing rebuild/disable paths, matching the new contract where syncSearchState never first-time enables FTS. Atomicity tests updated to mock the operations that actually occur (rebuildIndex/disableSearch) rather than enableSearch.
82c0745 to
04c8b49
Compare
What does this PR do?
Fixes a regression from #465 (
0a61ef4) that crashes playground initialization.syncSearchStatewas callingenableSearch()when FTS wasn't yet active, which triggered FTS5 operations (drop triggers, create virtual table, etc.) during field creation in the seed. The seed's ownenableSearchstep at the end handles failures gracefully with a try/catch, but the newcreateField→syncSearchStatepath didn't — so any FTS failure during field creation killed the entire playground init.Now
syncSearchStateonly:First-time FTS enablement stays with the seed's try-caught
enableSearchcall and the admin UI's explicit toggle.Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runAI-generated code disclosure