gatsbyjs/gatsby · error · Error
Range filter ${predicate} should not have value of type ${ty
Error message
Range filter ${predicate} should not have value of type ${typeof value} What it means
Same `resolveRangeEdge` path: a range predicate's value is a non-null object (not a primitive). LMDB keys cannot represent arbitrary objects, so the planner rejects it with the value's `typeof`.
Source
Thrown at packages/gatsby/src/datastore/lmdb/query/filter-using-index.ts:650
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:
* Get all items from index starting with ["foo"] prefix up to the next existing prefix:
*
* ```jsView on GitHub (pinned to 8b06340921)
Solutions
- Flatten the filter value to a scalar for range predicates.
- Inspect the filter object structure to ensure each comparator maps to a primitive.
Example fix
// before
filter: { age: { gt: { value: 10 } } }
// after
filter: { age: { gt: 10 } } Defensive patterns
Strategy: validation
Validate before calling
function validateRangeFilters(filter) {
for (const ops of Object.values(filter)) {
for (const [op, value] of Object.entries(ops)) {
if (["lt", "lte", "gt", "gte"].includes(op) && typeof value === "object" && value !== null && !Array.isArray(value)) {
throw new Error(`Range ${op} must be primitive, got object`)
}
}
}
}
Type guard
function isPrimitiveRangeValue(v: unknown): v is string | number | boolean | null {
return v === null || ["string", "number", "boolean"].includes(typeof v)
}
Prevention
- Flatten filter objects; never nest an object under a range comparator.
- Validate filters against a schema before sending the query.
When it happens
Trigger: `filter: { age: { gt: { value: 10 } } }` (object instead of scalar) on an indexed range field.
Common situations: Nested filter objects accidentally passed through; double-wrapped filter builders.
Related errors
- The argument to the `in` predicate should be an array
- ${filter.comparator} value must not be an array
- Range filter ${predicate} should not have array value
- Bad filter value for predicate ${filter.comparator}: ${inspe
- The $regex comparator is expecting the regex as a string, no
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/0d10430dabe72dcf.
Report an issue: GitHub.