{"record":{"id":"545cdffa1c5c8ed7","repo":"krisk/Fuse","slug":"empty-value-for-operator-op-on-key-key","errorCode":null,"errorMessage":"Empty value for operator '${op}' on key '${key}'","messagePattern":"Empty value for operator '(.+?)' on key '(.+?)'","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/search/extended/objectQuery.ts","lineNumber":150,"sourceCode":"      }\n      raw = clause[op]\n    }\n\n    if (!isString(raw)) {\n      throw new Error(\n        ErrorMsg.INVALID_FIELD_QUERY(\n          keyPath,\n          `value for '${valueOp}' must be a string`\n        )\n      )\n    }\n\n    // Normalize the value exactly as string syntax normalizes a pattern, THEN\n    // reject empty — `stripDiacritics` can empty a non-empty value (a lone\n    // combining mark), and an empty value would otherwise reach the matchers.\n    const value = normalizeValue(raw, options)\n    if (!value.length) {\n      throw new Error(ErrorMsg.EMPTY_QUERY_VALUE(valueOp, keyPath))\n    }\n\n    group.push(def.create(value, options))\n  }\n\n  return group\n}\n\n// Compile a `{ $and: [...] }` group into a single flattened AND group.\nfunction compileAndGroup(arr: any, keyPath: string, options: any): Matcher[] {\n  if (!isArray(arr) || !arr.length) {\n    throw new Error(\n      ErrorMsg.INVALID_FIELD_QUERY(keyPath, '$and must be a non-empty array')\n    )\n  }\n  const group: Matcher[] = []\n  for (let i = 0; i < arr.length; i += 1) {\n    // Each `$and` member is an operator-only clause; compileClause throws on any","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/krisk/Fuse/blob/edf2fb608eca0461508d1d71317e6e58309ffada/src/search/extended/objectQuery.ts#L132-L168","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Supply a non-empty value that survives normalization (e.g. a base character plus the mark, not a bare combining mark).","Check the value with normalizeValue (or the same stripDiacritics logic) before building the query and skip/drop empty clauses.","If the intent is to match docs lacking a value, use the appropriate negation operator with a meaningful value instead of an empty one.","Wrap query compilation in try/catch and surface a clear message to the user that their filter value is invalid after normalization."],"exampleFix":"// before\nconst q = { title: { $eq: '\\u0301' } } // lone combining mark -> throws\n// after\nconst value = '\\u00e9'.normalize('NFC') // or validate: if (!normalizeValue(v, options).length) skip clause\nconst q = { title: { $eq: value } }","handlingStrategy":"validation","validationCode":"import { normalizeValue } from './search/extended/objectQuery';\nfunction hasUsableValue(v, options) { return normalizeValue(v, options).length > 0; }\nif (!hasUsableValue(clauseValue, options)) throw new Error('Filter value is empty after normalization');","typeGuard":"function isNonEmptyAfterNormalize(v: unknown, options: unknown): boolean {\n  return typeof v === 'string' && normalizeValue(v, options).length > 0;\n}","tryCatchPattern":"try {\n  compileFieldQuery(fq, key, options);\n} catch (e) {\n  if (String(e.message).includes(\"Empty value for operator\")) {\n    // drop or fix the clause, inform user their value normalized to nothing\n  } else throw e;\n}","preventionTips":["Reject filter values that are only whitespace/combining marks at input time","Run the same normalization pipeline on user input before building queries","Test your diacritics options against edge-case inputs like lone combining marks","Fail early in your query builder when a clause value normalizes to ''"],"tags":["search","validation","unicode"],"backgroundTag":"empty-query-value","analyzedSha":"edf2fb608eca0461508d1d71317e6e58309ffada","analyzedAt":"2026-09-02T02:46:54.623Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}