{"record":{"id":"48332934cded8573","repo":"gatsbyjs/gatsby","slug":"the-argument-to-the-in-comparator-should-be-an-a","errorCode":null,"errorMessage":"The argument to the `in` comparator should be an array","messagePattern":"The argument to the `in` comparator should be an array","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/gatsby/src/datastore/in-memory/indexing.ts","lineNumber":706,"sourceCode":"    if (filterValue == null) {\n      // Edge case for null; fetch all nodes for `null` and `undefined` because\n      // `$eq` also returns nodes without the path when searching for `null`.\n      // Not all ops do so, so we map non-existing paths to `undefined`.\n\n      const arrNull = filterCache.byValue.get(null) ?? []\n      const arrUndef = filterCache.byValue.get(undefined) ?? []\n\n      // Merge the two (ordered) arrays and return an ordered deduped array\n      // TODO: is there a reason left why we cant just cache this merged list?\n      return unionNodesByCounter(arrNull, arrUndef)\n    }\n\n    return filterCache.byValue.get(filterValue)\n  }\n\n  if (op === `$in`) {\n    if (!Array.isArray(filterValue)) {\n      throw new Error(\"The argument to the `in` comparator should be an array\")\n    }\n    const filterValueArr: Array<FilterValueNullable> = filterValue\n\n    const set: Set<IGatsbyNodePartial> = new Set()\n\n    // TODO: we can also mergeSort for every step. this may perform worse because of how memory in js works.\n    // For every value in the needle array, find the bucket of nodes for\n    // that value, add this bucket of nodes to one list, return the list.\n    filterValueArr.forEach((v: FilterValueNullable) =>\n      filterCache.byValue.get(v)?.forEach(v => set.add(v))\n    )\n\n    const arr = [...set] // this is bad for perf but will guarantee us a unique set :(\n    arr.sort(sortByIds)\n\n    // Note: it's very unlikely that the list of filter values is big so .includes should be fine here\n    if (filterValueArr.includes(null)) {\n      // Like all other ops, `in: [null]` behaves weirdly, allowing all nodes","sourceCodeStart":688,"sourceCodeEnd":724,"githubUrl":"https://github.com/gatsbyjs/gatsby/blob/8b06340921ffdf23125a365b9c9923690cb62ce6/packages/gatsby/src/datastore/in-memory/indexing.ts#L688-L724","documentation":"The `in` comparator (`filter: { field: { in: [...] } }`) is implemented in the in-memory datastore runner and requires its value to be an Array. A scalar is rejected before bucket lookup because there is no single-value fast path for `in`.","triggerScenarios":"Writing `filter: { id: { in: \"abc\" } }` or passing a variable that resolved to a non-array.","commonSituations":"Passing a single id instead of a list; GraphQL variable typed as `ID` instead of `[ID]`; client code that sometimes returns one value.","solutions":["Wrap the value in an array: `in: [\"abc\"]`.","Type the GraphQL variable as a list, e.g. `[ID]!`.","Normalise at the caller so the value is always an array."],"exampleFix":"// before\nfilter: { id: { in: \"abc\" } }\n// after\nfilter: { id: { in: [\"abc\"] } }","handlingStrategy":"type-guard","validationCode":"function asArray<T>(v: T | T[]): T[] { return Array.isArray(v) ? v : [v] }\n// then: filter: { id: { in: asArray(ids) } }\n","typeGuard":"function isInFilterValue(v: unknown): v is unknown[] { return Array.isArray(v) }\n","tryCatchPattern":null,"preventionTips":["Type GraphQL variables for `in` as `[Type]!`.","Centralise filter construction so values are always normalised to arrays for `in`/`nin`."],"tags":["graphql","query","filter","datastore"],"backgroundTag":null,"analyzedSha":"8b06340921ffdf23125a365b9c9923690cb62ce6","analyzedAt":"2026-08-13T02:36:21.405Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}