tobi/qmd · error · Error

${location} (lex): ${error}

Error message

${location} (lex): ${error}

What it means

For search entries of type 'lex', the query is run through validateLexQuery() and the returned error string is re-thrown prefixed with the location. This covers FTS5/lex syntax problems other than newlines — e.g. unbalanced quotes or disallowed operators.

Source

Thrown at src/store.ts:5888

  const explain = options?.explain ?? false;
  const intent = options?.intent;
  const skipRerank = options?.skipRerank ?? false;
  const hooks = options?.hooks;

  const collections = options?.collections;

  if (searches.length === 0) return [];

  // Validate queries before executing
  for (const search of searches) {
    const location = search.line ? `Line ${search.line}` : 'Structured search';
    if (/[\r\n]/.test(search.query)) {
      throw new Error(`${location} (${search.type}): queries must be single-line. Remove newline characters.`);
    }
    if (search.type === 'lex') {
      const error = validateLexQuery(search.query);
      if (error) {
        throw new Error(`${location} (lex): ${error}`);
      }
    } else if (search.type === 'vec' || search.type === 'hyde') {
      const error = validateSemanticQuery(search.query);
      if (error) {
        throw new Error(`${location} (${search.type}): ${error}`);
      }
    }
  }

  const rankedLists: RankedResult[][] = [];
  const rankedListMeta: RankedListMeta[] = [];
  const docidMap = new Map<string, string>(); // filepath -> docid
  const hasVectors = !!store.db.prepare(
    `SELECT name FROM sqlite_master WHERE type='table' AND name='vectors_vec'`
  ).get();

  // Helper to run search across collections (or all if undefined)
  const collectionList = collections ?? [undefined]; // undefined = all collections

View on GitHub (pinned to dbfd0b4736)

Solutions

  1. Use the lex query escaping helpers / wrap user phrases in double quotes properly
  2. Show validateLexQuery's message to the user and let them fix the query
  3. Fall back to a plain sanitized term list

Example fix

// before
searchMulti([{ type: 'lex', query: '"unclosed' }]);
// after
const err = validateLexQuery(q);
if (err) throw new Error(`bad query: ${err}`);
searchMulti([{ type: 'lex', query: sanitize(q) }]);
Defensive patterns

Strategy: validation

Validate before calling

const err = validateLexQuery(q); if (!err) searchMulti([{ type: 'lex', query: q }]); else report(err);

Try / catch

try { searchMulti(s); } catch (e) { if (/\(lex\)/.test((e as Error).message)) return friendlyError(e); throw e; }

Prevention

When it happens

Trigger: Passing a lex query like `"unclosed phrase` or operators the lexer grammar rejects to searchMulti(); validateLexQuery returns an error message which is thrown verbatim.

Common situations: User-supplied raw FTS5 syntax without escaping; stray double quotes; copied SQL-ish queries with unsupported syntax.

Related errors


AI-assisted analysis of tobi/qmd@dbfd0b4736 (2026-08-28). Data as JSON: /api/errors/0079f788ac5d2c85. Report an issue: GitHub.