gatsbyjs/gatsby · error · Error

${filter.comparator} value must not be an array

Error message

${filter.comparator} value must not be an array

What it means

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.

Source

Thrown at packages/gatsby/src/datastore/lmdb/query/filter-using-index.ts:541

      let hasNull = false
      for (const item of new Set(arr)) {
        const value = toIndexFieldValue(item, filter)
        if (value === null) hasNull = true
        rangeStarts.push(value)
        rangeEndings.push(getValueEdgeAfter(value))
      }
      // Special case: { eq: null } or { in: [null, `any`]} must also include values for undefined!
      if (hasNull) {
        rangeStarts.push(undefinedSymbol)
        rangeEndings.push(getValueEdgeAfter(undefinedSymbol))
      }
      break
    }
    case DbComparator.LT:
    case DbComparator.LTE: {
      if (Array.isArray(filter.value))
        throw new Error(`${filter.comparator} value must not be an array`)

      const value = toIndexFieldValue(filter.value, filter)
      const end =
        filter.comparator === DbComparator.LT ? value : getValueEdgeAfter(value)

      // Try to find matching GTE/GT filter
      const start =
        resolveRangeEdge(context, field, DbComparator.GTE) ??
        resolveRangeEdge(context, field, DbComparator.GT, ValueEdges.AFTER)

      // Do not include null or undefined in results unless null was requested explicitly
      //
      // Index ordering:
      //  BinaryInfinityNegative
      //  null
      //  Symbol(`undef`)
      //  -10
      //  10

View on GitHub (pinned to 8b06340921)

Solutions

  1. Pass a single scalar to `lt`/`lte`.
  2. Use `in`/`nin` or split into multiple queries if a set of upper bounds is needed.

Example fix

// before
filter: { age: { lt: [10, 20] } }
// after
filter: { age: { lt: 20 } }
Defensive patterns

Strategy: validation

Validate before calling

function assertScalarRange(op, value) {
  if (["lt", "lte"].includes(op) && Array.isArray(value)) {
  throw new Error(`${op} must be scalar`)
  }
}

Type guard

function isRangeScalar(v: unknown): v is string | number | boolean | null {
  return v === null || ["string", "number", "boolean"].includes(typeof v)
}

Prevention

When it happens

Trigger: `filter: { age: { lt: [10, 20] } }` against an indexed field.

Common situations: Variable reuse; building filters generically and always wrapping values in arrays.

Related errors


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