gatsbyjs/gatsby · error · Error

Range filter ${predicate} should not have array value

Error message

Range filter ${predicate} should not have array value

What it means

While resolving a complementary range edge (e.g. looking up a `gt` when planning an `lt`), `resolveRangeEdge` finds an unused filter statement for the same predicate whose value is an Array. Range predicates require scalar values, so it throws with the predicate name.

Source

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

function resolveRangeEdge(
  context: IFilterContext,
  indexField: string,
  predicate: DbComparator,
  edge: ValueEdges = ValueEdges.EQ
): IndexFieldValue | RangeEdgeBefore | RangeEdgeAfter | undefined {
  const fieldQueries = getFieldQueries(context.dbQueries, indexField)
  for (const dbQuery of fieldQueries) {
    if (context.usedQueries.has(dbQuery)) {
      continue
    }
    const filterStatement = getFilterStatement(dbQuery)
    if (filterStatement.comparator !== predicate) {
      continue
    }
    context.usedQueries.add(dbQuery)
    const value = filterStatement.value
    if (Array.isArray(value)) {
      throw new Error(`Range filter ${predicate} should not have array value`)
    }
    if (typeof value === `object` && value !== null) {
      throw new Error(
        `Range filter ${predicate} should not have value of type ${typeof value}`
      )
    }
    if (edge === 0) {
      return value
    }
    return edge < 0 ? getValueEdgeBefore(value) : getValueEdgeAfter(value)
  }
  return undefined
}

/**
 * Returns the edge after the given value, suitable for lmdb range queries.
 *
 * Example:

View on GitHub (pinned to 8b06340921)

Solutions

  1. Make every range predicate (`gt`/`gte`/`lt`/`lte`) a scalar.
  2. Audit the filter object literal for stray array values.

Example fix

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

Strategy: validation

Validate before calling

const RANGE = new Set(["lt", "lte", "gt", "gte"])
function validateRangeFilters(filter) {
  for (const ops of Object.values(filter)) {
  for (const [op, value] of Object.entries(ops)) {
  if (RANGE.has(op) && Array.isArray(value)) throw new Error(`Range ${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: Combining range filters where one of them carries an array value, e.g. `{ age: { lt: 30 }, age: { gt: [10, 20] } }`.

Common situations: Programmatic filter construction producing arrays for range operators.

Related errors


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