Automattic/mongoose · error · Error
Got null array filter in ${arrayFilters}
Error message
Got null array filter in ${arrayFilters} What it means
Mongoose validates every entry of the arrayFilters option used with 'a.$[identifier]' update paths. A null or undefined entry in the arrayFilters array is always a client-side bug (usually from building the array dynamically), so Mongoose throws this plain Error before sending the update to MongoDB.
Source
Thrown at lib/helpers/update/castArrayFilters.js:42
}
if (schema._userProvidedOptions.strictQuery != null) {
strictQuery = schema._userProvidedOptions.strictQuery;
}
if (query._mongooseOptions.strictQuery != null) {
strictQuery = query._mongooseOptions.strictQuery;
}
_castArrayFilters(arrayFilters, schema, strictQuery, updatedPathsByFilter, query);
};
function _castArrayFilters(arrayFilters, schema, strictQuery, updatedPathsByFilter, query) {
// Map to store discriminator values for embedded documents in the array filters.
// This is used to handle cases where array filters target specific embedded document types.
const discriminatorValueMap = {};
for (const filter of arrayFilters) {
if (filter == null) {
throw new Error(`Got null array filter in ${arrayFilters}`);
}
const keys = Object.keys(filter).filter(key => filter[key] != null);
if (keys.length === 0) {
continue;
}
const firstKey = keys[0];
if (firstKey === '$and' || firstKey === '$or') {
for (const key of keys) {
_castArrayFilters(filter[key], schema, strictQuery, updatedPathsByFilter, query);
}
continue;
}
const dot = firstKey.indexOf('.');
const filterWildcardPath = dot === -1 ? firstKey : firstKey.substring(0, dot);
if (updatedPathsByFilter[filterWildcardPath] == null) {
continue;
}View on GitHub (pinned to 49cdab0136)
Solutions
- Filter out nullish entries: arrayFilters: filters.filter(f => f != null)
- Provide exactly one non-null object per identifier used in the update paths
- Use [{}] (empty object matches all array elements) when you genuinely need an unconditioned filter, never null
Example fix
// before
const filters = [cond ? { 'elem.a': cond } : null];
await Model.updateOne({}, { $set: { 'items.$[elem].qty': 5 } }, { arrayFilters: filters });
// after
const filters = [{ 'elem.a': cond ?? { $exists: true } }];
await Model.updateOne({}, { $set: { 'items.$[elem].qty': 5 } }, { arrayFilters: filters.filter(f => f != null) }); Defensive patterns
Strategy: validation
Validate before calling
// Validate arrayFilters before executing the update
function validArrayFilters(filters) {
if (!Array.isArray(filters) || filters.some(f => f == null || typeof f !== 'object')) {
throw new Error('arrayFilters must be an array of non-null objects');
}
return filters;
} Type guard
const hasValidArrayFilters = (opts) => !opts?.arrayFilters || (Array.isArray(opts.arrayFilters) && opts.arrayFilters.every(f => f != null && typeof f === 'object' && !Array.isArray(f)));
Try / catch
try {
await Model.updateOne(f, u, { arrayFilters });
} catch (err) {
if (/null array filter/.test(err.message)) {
// rebuild arrayFilters with .filter(f => f != null) and retry
} else throw err;
} Prevention
- Filter arrayFilters with .filter(f => f != null) whenever built dynamically
- Use [{}] for unconditional element matching instead of null
- Add runtime assertions on update options in shared data-access helpers
When it happens
Trigger: Model.updateOne({}, { $set: { 'items.$[elem].qty': 5 } }, { arrayFilters: [null] }) or arrays assembled with holes/optionals: arrayFilters: [...maybeFilters, undefined], [{ 'elem.a': 1 }, undefined], or .map() callbacks that return undefined for some inputs.
Common situations: Building arrayFilters from optional request parameters; conditional spreads leaving undefined slots; copying documentation examples with placeholder entries; API gateways deserializing missing objects as null.
Related errors
- Invalid atomic update value for ${op}. Expected an object, r
- Could not find path "${filterPath}" in schema
- Path '${path}' contains the same array filter multiple times
- Arguments must be aggregate pipeline operators
- Aggregate `near()` argument must have a `near` property
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/5020e78eb4148e60.
Report an issue: GitHub.