krisk/Fuse · error · Error

Empty value for operator '${op}' on key '${key}'

Error message

Empty value for operator '${op}' on key '${key}'

What it means

Thrown by compileClause when an operator clause's value becomes empty after normalization (normalizeValue applies stripDiacritics, which can reduce a lone combining mark to an empty string). The library rejects empty operator values up front because matchers cannot meaningfully match nothing. It mirrors the string-syntax normalization so both query forms behave identically.

Source

Thrown at src/search/extended/objectQuery.ts:150

      }
      raw = clause[op]
    }

    if (!isString(raw)) {
      throw new Error(
        ErrorMsg.INVALID_FIELD_QUERY(
          keyPath,
          `value for '${valueOp}' must be a string`
        )
      )
    }

    // Normalize the value exactly as string syntax normalizes a pattern, THEN
    // reject empty — `stripDiacritics` can empty a non-empty value (a lone
    // combining mark), and an empty value would otherwise reach the matchers.
    const value = normalizeValue(raw, options)
    if (!value.length) {
      throw new Error(ErrorMsg.EMPTY_QUERY_VALUE(valueOp, keyPath))
    }

    group.push(def.create(value, options))
  }

  return group
}

// Compile a `{ $and: [...] }` group into a single flattened AND group.
function compileAndGroup(arr: any, keyPath: string, options: any): Matcher[] {
  if (!isArray(arr) || !arr.length) {
    throw new Error(
      ErrorMsg.INVALID_FIELD_QUERY(keyPath, '$and must be a non-empty array')
    )
  }
  const group: Matcher[] = []
  for (let i = 0; i < arr.length; i += 1) {
    // Each `$and` member is an operator-only clause; compileClause throws on any

View on GitHub (pinned to edf2fb608e)

Solutions

  1. Supply a non-empty value that survives normalization (e.g. a base character plus the mark, not a bare combining mark).
  2. Check the value with normalizeValue (or the same stripDiacritics logic) before building the query and skip/drop empty clauses.
  3. If the intent is to match docs lacking a value, use the appropriate negation operator with a meaningful value instead of an empty one.
  4. Wrap query compilation in try/catch and surface a clear message to the user that their filter value is invalid after normalization.

Example fix

// before
const q = { title: { $eq: '\u0301' } } // lone combining mark -> throws
// after
const value = '\u00e9'.normalize('NFC') // or validate: if (!normalizeValue(v, options).length) skip clause
const q = { title: { $eq: value } }
Defensive patterns

Strategy: validation

Validate before calling

import { normalizeValue } from './search/extended/objectQuery';
function hasUsableValue(v, options) { return normalizeValue(v, options).length > 0; }
if (!hasUsableValue(clauseValue, options)) throw new Error('Filter value is empty after normalization');

Type guard

function isNonEmptyAfterNormalize(v: unknown, options: unknown): boolean {
  return typeof v === 'string' && normalizeValue(v, options).length > 0;
}

Try / catch

try {
  compileFieldQuery(fq, key, options);
} catch (e) {
  if (String(e.message).includes("Empty value for operator")) {
    // drop or fix the clause, inform user their value normalized to nothing
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the extended (object) search query with a clause like { $eq: '\u0301' } (a lone combining mark) or any value that normalizes to '' via normalizeValue(raw, options) — e.g. a value consisting only of diacritics stripped by the current locale/diacritics options.

Common situations: Passing user-supplied filter values that contain only accents/combining characters; pasting text from sources where only a combining mark survives; misconfigured stripDiacritics options stripping content the user expected to keep.

Related errors


AI-assisted analysis of krisk/Fuse@edf2fb608e (2026-09-02). Data as JSON: /api/errors/545cdffa1c5c8ed7. Report an issue: GitHub.