gatsbyjs/gatsby · error
The $nin operator expects an array as value
Error message
The $nin operator expects an array as value
What it means
In-memory datastore guard in getNodesFromCacheByValue: the $nin (not-in) filter operator requires its value to be an array so it can build a Set of excluded values. The GraphQL filter passed a non-array value to $nin.
Solutions
- Wrap the value in an array: `nin: ["draft"]`.
- Use a list GraphQL variable type.
- If you meant a single exclude, consider `$ne` instead.
Example fix
// before
filter: { status: { nin: "draft" } }
// after
filter: { status: { nin: ["draft"] } } Defensive patterns
Strategy: type-guard
Validate before calling
function asArray<T>(v: T | T[]): T[] { return Array.isArray(v) ? v : [v] }
// filter: { status: { nin: asArray(excluded) } }
Type guard
function isNinFilterValue(v: unknown): v is unknown[] { return Array.isArray(v) }
Prevention
- Type GraphQL variables for `nin` as `[Type]!`.
- Use `$ne` when excluding a single value.
When it happens
Trigger: `filter: { status: { nin: "draft" } }` or a non-array variable.
Common situations: Same as `$in`: scalar passed instead of list; mistyped GraphQL variable.
Related errors
- Array is an invalid filter value for the
- Bad filter value for predicate
- value must not be an array
- Range filter should not have array value
- Range filter should not have value of type
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/f373ee6ab6d0ce6a.
Report an issue: GitHub.
Appendix: source
Thrown at packages/gatsby/src/datastore/in-memory/indexing.ts:746
// This will also dedupe so don't do that immediately
return unionNodesByCounter(nodes, arr)
}
}
// elemMatch can cause a node to appear in multiple buckets so we must dedupe first
if (wasElemMatch) {
expensiveDedupeInline(arr)
}
return arr
}
if (op === `$nin`) {
// This is essentially the same as the $ne operator, just with multiple
// values to exclude.
if (!Array.isArray(filterValue)) {
throw new Error(`The $nin operator expects an array as value`)
}
const values: Set<FilterValueNullable> = new Set(filterValue)
const set = new Set(filterCache.meta.nodesUnordered)
// Do the action for "$ne" for each element in the set of values
values.forEach(filterValue => {
removeBucketFromSet(filterValue, filterCache, set)
})
// TODO: there's probably a more efficient algorithm to do set
// subtraction in such a way that we don't have to re-sort
return [...set].sort(sortByIds)
}
if (op === `$ne`) {
const set = new Set(filterCache.meta.nodesUnordered)
View on GitHub (pinned to 8b06340921)