{"record":{"id":"36a602a762e9c6eb","repo":"nodejs/node","slug":"und-err-invalid-arg-36a602","errorCode":"UND_ERR_INVALID_ARG","errorMessage":"options.operator must to be a case insensitive string equal to 'OR' or 'AND'","messagePattern":"options\\.operator must to be a case insensitive string equal to 'OR' or 'AND'","errorType":"validation","errorClass":"InvalidArgumentError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/mock/mock-call-history.js","lineNumber":25,"sourceCode":"  switch (options.operator) {\n    case 'OR':\n      store.push(...handler(criteria, allLogs))\n\n      return store\n    case 'AND':\n      return handler(criteria, store)\n    default:\n      // guard -- should never happens because buildAndValidateFilterCallsOptions is called before\n      throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \\'OR\\' or \\'AND\\'')\n  }\n}\n\nfunction buildAndValidateFilterCallsOptions (options = {}) {\n  const finalOptions = {}\n\n  if ('operator' in options) {\n    if (typeof options.operator !== 'string' || (options.operator.toUpperCase() !== 'OR' && options.operator.toUpperCase() !== 'AND')) {\n      throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \\'OR\\' or \\'AND\\'')\n    }\n\n    return {\n      ...finalOptions,\n      operator: options.operator.toUpperCase()\n    }\n  }\n\n  return finalOptions\n}\n\nfunction makeFilterCalls (parameterName) {\n  return (parameterValue, logs = this.logs) => {\n    if (typeof parameterValue === 'string' || parameterValue == null) {\n      return logs.filter((log) => {\n        return log[parameterName] === parameterValue\n      })\n    }","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/mock/mock-call-history.js#L7-L43","documentation":"Thrown by the mock call-history filter logic (`InvalidArgumentError`, code `UND_ERR_INVALID_ARG`) when `options.operator` is present in a `filterCalls` criteria-options object but is not a case-insensitive `'OR'` or `'AND'`. The operator controls how multiple criteria keys (protocol, host, path, method, etc.) are combined: `OR` returns the union (default), `AND` returns only logs matching every criterion. Validation runs in `buildAndValidateFilterCallsOptions` before filtering. There is a second, near-identical throw inside `handleFilterCallsWithOptions` that exists only as a defensive guard and should be unreachable if validation ran.","triggerScenarios":"Calling `callHistory.filterCalls(criteria, { operator: 'XOR' })`, `{ operator: 'or' }` is fine (case-insensitive), but `{ operator: 'NOT' }`, `{ operator: true }`, or `{ operator: '' }` throws. The guard is `typeof options.operator !== 'string' || (toUpperCase !== 'OR' && toUpperCase !== 'AND')`.","commonSituations":"Assuming additional boolean operators are supported; passing a lowercased value works but `operator: 'AND'`/`'OR'` only; passing a non-string from config; reaching the unreachable guard via a code path that skips validation (internal misuse).","solutions":["Use `operator: 'OR'` (default, union semantics) or `operator: 'AND'` (intersection semantics), case-insensitive.","Omit the option entirely to get the default `OR` behavior.","If you need richer boolean logic, post-filter the returned logs in your own code."],"exampleFix":"// before\nhistory.filterCalls({ path: '/x', method: 'GET' }, { operator: 'XOR' })\nhistory.filterCalls({ path: '/x' }, { operator: true })\n\n// after\nhistory.filterCalls({ path: '/x', method: 'GET' }, { operator: 'AND' })\nhistory.filterCalls({ path: '/x' }, { operator: 'OR' })\nhistory.filterCalls({ path: '/x' }) // default OR","handlingStrategy":"validation","validationCode":"function validateOperator(operator) {\n  if (operator == null) return 'OR'\n  if (typeof operator !== 'string') throw new Error('operator must be a string')\n  const up = operator.toUpperCase()\n  if (up !== 'OR' && up !== 'AND') throw new Error('operator must be OR or AND')\n  return up\n}","typeGuard":"function isFilterOperator(v) {\n  return typeof v === 'string' && ['OR', 'AND'].includes(v.toUpperCase())\n}","tryCatchPattern":null,"preventionTips":["Use only 'OR'/'AND' (case-insensitive) or omit the option for OR.","Do post-filtering for richer boolean logic."],"tags":["undici","mock","call-history","filter","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}