gatsbyjs/gatsby · error
Array is an invalid filter value for the `${op}` comparator
Error message
Array is an invalid filter value for the `${op}` comparator What it means
When the in-memory evaluator reaches the scalar comparator branch (`$lt`, `$gt`, `$lte`, `$gte`, `$eq`, `$ne`, `$regex`/`$glob`), an Array value is meaningless and explicitly rejected. Arrays are only valid for `$in`/`$nin` (handled earlier). A `RegExp` instance here is also flagged as internal misuse.
Source
Thrown at packages/gatsby/src/datastore/in-memory/indexing.ts:820
expensiveDedupeInline(arr)
}
return arr
}
if (filterValue == null) {
if (op === `$lt` || op === `$gt`) {
// Nothing is lt/gt null
return undefined
}
// This is an edge case and this value should be directly indexed
// For `lte`/`gte` this should only return nodes for `null`, not a "range"
return filterCache.byValue.get(filterValue)
}
if (Array.isArray(filterValue)) {
throw new Error(
"Array is an invalid filter value for the `" + op + "` comparator"
)
}
if (filterValue instanceof RegExp) {
// This is most likely an internal error, although it is possible for
// users to talk to this API more directly.
throw new Error(
`A RegExp instance is only valid for $regex and $glob comparators`
)
}
if (op === `$lt`) {
// First try a direct approach. If a value is queried that also exists then
// we can prevent a binary search through the whole list, O(1) vs O(log n)
const ranges = filterCache.meta.valueRangesAsc
const nodes = filterCache.meta.nodesByValueAscView on GitHub (pinned to 8b06340921)
Solutions
- Pass a scalar to range/equality comparators.
- Switch to `in`/`nin` if a set is genuinely intended.
- Let Gatsby compile regex via the `regex`/`glob` string operators rather than passing `RegExp` instances.
Example fix
// before
filter: { age: { gte: [18] } }
// after
filter: { age: { gte: 18 } } Defensive patterns
Strategy: validation
Validate before calling
// Reject arrays for scalar comparators before sending the query.
const SCALAR_OPS = new Set(["eq", "ne", "lt", "lte", "gt", "gte", "regex", "glob"])
function validateFilter(filter) {
for (const [field, ops] of Object.entries(filter)) {
for (const [op, value] of Object.entries(ops)) {
if (SCALAR_OPS.has(op) && Array.isArray(value)) {
throw new Error(`${field}.${op} must be a scalar, got array`)
}
}
}
}
Type guard
function isScalarComparatorValue(v: unknown): boolean {
return v === null || (typeof v !== "object" && typeof v !== "undefined")
}
Prevention
- Keep a single filter-builder with per-operator type rules.
- Never reuse the same variable across `in` and range filters.
When it happens
Trigger: `filter: { age: { gte: [18] } }`, or piping an array into a scalar comparator; passing a pre-built `RegExp` to a non-regex comparator.
Common situations: Reusing a variable across `in` and range filters; programmatic filter builders that always wrap values in arrays.
Related errors
- The $regex comparator is expecting the regex as a string, no
- The argument to the `in` comparator should be an array
- The $nin operator expects an array as value
- The argument to the `in` predicate should be an array
- ${filter.comparator} value must not be an array
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/a4dbfc32f96bc0f8.
Report an issue: GitHub.