Skip to content

fix(core): /search/suggest crash from double-star FTS5 prefix (#547)#558

Merged
ascorbic merged 1 commit intoemdash-cms:mainfrom
csfalcao:fix/547-fts5-suggest-double-star
Apr 14, 2026
Merged

fix(core): /search/suggest crash from double-star FTS5 prefix (#547)#558
ascorbic merged 1 commit intoemdash-cms:mainfrom
csfalcao:fix/547-fts5-suggest-double-star

Conversation

@csfalcao
Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes the /_emdash/api/search/suggest 500 error filed in #547. getSuggestions in packages/core/src/search/query.ts was appending * on top of the * that escapeQuery already appends to each term, producing invalid FTS5 like "des"** and raising SqliteError: fts5: syntax error near "*" on every request.

-		// Use prefix search for autocomplete
-		const prefixQuery = `${escapeQuery(query)}*`;
-		if (!prefixQuery || prefixQuery === "*") {
+		// Use prefix search for autocomplete. `escapeQuery` already appends `*`
+		// to each term for prefix matching, so we must not append another one.
+		const prefixQuery = escapeQuery(query);
+		if (!prefixQuery) {
 			continue;
 		}

escapeQuery returns "des"* for "des" (line 395 in the same file), so simply passing its output to MATCH is the correct thing to do. The prefixQuery === "*" guard is no longer reachable now that the literal * is gone, so the check is simplified to !prefixQuery.

A regression test is added at packages/core/tests/integration/search/suggest.test.ts:

  • returns matching suggestions for a plain prefix query — reproduces the crash on main, passes after the fix.
  • returns empty array for a non-matching query — guards against the returned shape regressing.

Closes #547. Follow-up to PR #424 (where I intentionally kept this out of scope per AGENTS.md).

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes (baseline on main is 11 pre-existing diagnostics in unrelated files; this PR does not add any)
  • pnpm test passes (new suggest tests green; the one pre-existing failure in tests/integration/plugins/capabilities.test.ts "does not throw for any host" reproduces on pristine main too and is unrelated to this change — verified by checking out origin/main and running the same test)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation (N/A — no UI changes)
  • I have added a changeset
  • New features link to an approved Discussion (N/A — bug fix)

AI-generated code disclosure

  • This PR includes AI-generated code

Screenshots / test output

Before (main at 82c6345):

$ pnpm vitest run tests/integration/search/suggest.test.ts
FAIL  tests/integration/search/suggest.test.ts > getSuggestions (Integration) > returns matching suggestions for a plain prefix query
SqliteError: fts5: syntax error near "*"
 ❯ getSuggestions src/search/query.ts:284:19
Tests  2 failed (2)

After this PR:

$ pnpm vitest run tests/integration/search/suggest.test.ts
✓ tests/integration/search/suggest.test.ts (2 tests) 52ms
Tests  2 passed (2)

`escapeQuery` already appends `*` to each term for prefix matching, so
`getSuggestions` must not append another one. `${escapeQuery(q)}*`
produced `"des"**`, which is invalid FTS5 and raised
`SqliteError: fts5: syntax error near "*"` on every /search/suggest
request.

Adds an integration test that reproduces the crash with a plain prefix
query and another asserting a non-matching query returns an empty array.

Closes emdash-cms#547.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 14, 2026

🦋 Changeset detected

Latest commit: 3229c03

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
create-emdash Patch
@emdash-cms/plugin-embeds Patch

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 14, 2026

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@558

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@558

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@558

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@558

emdash

npm i https://pkg.pr.new/emdash@558

create-emdash

npm i https://pkg.pr.new/create-emdash@558

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@558

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@558

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@558

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@558

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@558

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@558

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@558

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@558

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@558

commit: 3229c03

Copy link
Copy Markdown
Collaborator

@ascorbic ascorbic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@ascorbic ascorbic merged commit 629fe1d into emdash-cms:main Apr 14, 2026
26 checks passed
@emdashbot emdashbot bot mentioned this pull request Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/search/suggest returns 500 — double "*" prefix produces invalid FTS5 syntax

2 participants