{"record":{"id":"4703e685a95ef14a","repo":"gatsbyjs/gatsby","slug":"filter-comparator-value-must-not-be-an-array","errorCode":null,"errorMessage":"${filter.comparator} value must not be an array","messagePattern":"(.+?) value must not be an array","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/gatsby/src/datastore/lmdb/query/filter-using-index.ts","lineNumber":541,"sourceCode":"\n      let hasNull = false\n      for (const item of new Set(arr)) {\n        const value = toIndexFieldValue(item, filter)\n        if (value === null) hasNull = true\n        rangeStarts.push(value)\n        rangeEndings.push(getValueEdgeAfter(value))\n      }\n      // Special case: { eq: null } or { in: [null, `any`]} must also include values for undefined!\n      if (hasNull) {\n        rangeStarts.push(undefinedSymbol)\n        rangeEndings.push(getValueEdgeAfter(undefinedSymbol))\n      }\n      break\n    }\n    case DbComparator.LT:\n    case DbComparator.LTE: {\n      if (Array.isArray(filter.value))\n        throw new Error(`${filter.comparator} value must not be an array`)\n\n      const value = toIndexFieldValue(filter.value, filter)\n      const end =\n        filter.comparator === DbComparator.LT ? value : getValueEdgeAfter(value)\n\n      // Try to find matching GTE/GT filter\n      const start =\n        resolveRangeEdge(context, field, DbComparator.GTE) ??\n        resolveRangeEdge(context, field, DbComparator.GT, ValueEdges.AFTER)\n\n      // Do not include null or undefined in results unless null was requested explicitly\n      //\n      // Index ordering:\n      //  BinaryInfinityNegative\n      //  null\n      //  Symbol(`undef`)\n      //  -10\n      //  10","sourceCodeStart":523,"sourceCodeEnd":559,"githubUrl":"https://github.com/gatsbyjs/gatsby/blob/8b06340921ffdf23125a365b9c9923690cb62ce6/packages/gatsby/src/datastore/lmdb/query/filter-using-index.ts#L523-L559","documentation":"For `lt`/`lte` index range planning, the filter value must be a scalar so a single range boundary can be computed. An array is rejected because it would imply multiple boundaries that `lt`/`lte` cannot represent.","triggerScenarios":"`filter: { age: { lt: [10, 20] } }` against an indexed field.","commonSituations":"Variable reuse; building filters generically and always wrapping values in arrays.","solutions":["Pass a single scalar to `lt`/`lte`.","Use `in`/`nin` or split into multiple queries if a set of upper bounds is needed."],"exampleFix":"// before\nfilter: { age: { lt: [10, 20] } }\n// after\nfilter: { age: { lt: 20 } }","handlingStrategy":"validation","validationCode":"function assertScalarRange(op, value) {\n  if ([\"lt\", \"lte\"].includes(op) && Array.isArray(value)) {\n  throw new Error(`${op} must be scalar`)\n  }\n}\n","typeGuard":"function isRangeScalar(v: unknown): v is string | number | boolean | null {\n  return v === null || [\"string\", \"number\", \"boolean\"].includes(typeof v)\n}\n","tryCatchPattern":null,"preventionTips":["Pass single scalars to `lt`/`lte`/`gt`/`gte`.","Centralise filter construction with per-operator validators."],"tags":["graphql","query","filter","lmdb","indexing","datastore"],"backgroundTag":null,"analyzedSha":"8b06340921ffdf23125a365b9c9923690cb62ce6","analyzedAt":"2026-08-13T02:36:21.405Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}