hcengineering/platform · error · Error
$in predicate requires array
Error message
$in predicate requires array
What it means
The $in query predicate must be given an array of candidate values. The factory in predicate.ts validates its argument eagerly and throws this error when the value passed after $in is not an Array, because membership testing (o.some(p => value === p)) only makes sense over a list. This matches MongoDB semantics where $in takes an array.
Source
Thrown at foundations/core/packages/core/src/predicate.ts:42
type PredicateFactory = (pred: any, propertyKey: string) => Predicate
type ExecPredicate = (value: any) => boolean
function execPredicate (docs: Doc[], propertyKey: string, pred: ExecPredicate): Doc[] {
const result: Doc[] = []
for (const doc of docs) {
const value = getObjectValue(propertyKey, doc)
if (pred(value)) {
result.push(doc)
}
}
return result
}
const predicates: Record<string, PredicateFactory> = {
$in: (o, propertyKey) => {
if (!Array.isArray(o)) {
throw new Error('$in predicate requires array')
}
return (docs) =>
execPredicate(docs, propertyKey, (value) => {
if (Array.isArray(value)) {
return o.some((p) => value.includes(p))
} else {
// eslint-disable-next-line eqeqeq
return o.some((p) => p == value)
}
})
},
$all: (o, propertyKey) => {
if (!Array.isArray(o)) {
throw new Error('$all predicate requires array')
}
return (docs) =>
execPredicate(docs, propertyKey, (value: any[]) => {
for (const val of o) {View on GitHub (pinned to 63e28dc964)
Solutions
- Wrap the value in an array: { $in: [value] } instead of { $in: value }.
- Guard dynamic values with Array.isArray before building the query and normalize single values to [value].
- Check upstream code that produces the list (API call, map/filter) to ensure it returns an array, not undefined.
Example fix
// before
const q = { status: { $in: statusesFromApi } }
// after
const list = Array.isArray(statusesFromApi) ? statusesFromApi : statusesFromApi != null ? [statusesFromApi] : []
const q = { status: { $in: list } } Defensive patterns
Strategy: type-guard
Validate before calling
function asArray<T>(v: T | T[] | undefined | null): T[] {
return Array.isArray(v) ? v : v != null ? [v] : []
}
const q = { status: { $in: asArray(statuses) } } Type guard
function isArrayOrThrow<T>(v: unknown): asserts v is T[] {
if (!Array.isArray(v)) throw new TypeError('$in expects an array of values')
} Try / catch
try {
return await find(clazz, query)
} catch (e) {
if (e instanceof Error && e.message.includes('predicate requires array')) {
return await find(clazz, normalizeQueryArrays(query))
}
throw e
} Prevention
- Always normalize single values to arrays before building $in clauses.
- Type query-builder inputs as readonly T[] so scalars fail at compile time.
- Check API/config paths that supply lists for undefined before querying.
When it happens
Trigger: Building a query like { status: { $in: 'active' } } (a bare string), { _id: { $in: someId } } where someId failed to come back as an array, or spreading a possibly-undefined variable: { $in: maybeIds } when maybeIds is undefined or a single object.
Common situations: Passing a single value instead of wrapping it in an array; a result of Array.prototype.filter/map or an API response expected to be an array but actually undefined/null; deserialized query params (JSON config, URL query) arriving as a scalar.
Related errors
- $all predicate requires array
- $nin predicate requires array
- $size predicate requires array
- unknown predicate:
- unknown operator: ${name}
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/ba045523b9ab5d3a.
Report an issue: GitHub.