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.nodesByValueAsc

View on GitHub (pinned to 8b06340921)

Solutions

  1. Pass a scalar to range/equality comparators.
  2. Switch to `in`/`nin` if a set is genuinely intended.
  3. 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

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


AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13). Data as JSON: /api/errors/a4dbfc32f96bc0f8. Report an issue: GitHub.