Automattic/mongoose · error · TypeError
Invalid $within $box argument. Expected an array, received $
Error message
Invalid $within $box argument. Expected an array, received ${arr} What it means
When casting $within (and $geoWithin legacy shapes) with $box or $polygon, Mongoose iterates the argument and requires every entry to be an array of coordinates, which it then casts to numbers. If any entry is not an array — a flattened number, a string, an object — it throws TypeError 'Invalid $within $box argument. Expected an array, received <val>'.
Source
Thrown at lib/schema/operators/geospatial.js:66
// ignore unknowns
break;
}
_castMinMaxDistance(self, val);
return val;
}
function cast$within(val) {
_castMinMaxDistance(this, val);
if (val.$box || val.$polygon) {
const type = val.$box ? '$box' : '$polygon';
val[type].forEach(arr => {
if (!Array.isArray(arr)) {
const msg = 'Invalid $within $box argument. '
+ 'Expected an array, received ' + arr;
throw new TypeError(msg);
}
arr.forEach((v, i) => {
arr[i] = castToNumber.call(this, v);
});
});
} else if (val.$center || val.$centerSphere) {
const type = val.$center ? '$center' : '$centerSphere';
val[type].forEach((item, i) => {
if (Array.isArray(item)) {
item.forEach((v, j) => {
item[j] = castToNumber.call(this, v);
});
} else {
val[type][i] = castToNumber.call(this, item);
}
});
} else if (val.$geometry) {
cast$geometry(val, this);View on GitHub (pinned to 49cdab0136)
Solutions
- Pass $box as exactly two coordinate arrays: `{ $box: [[x1, y1], [x2, y2]] }` (bottom-left then top-right, [lng, lat])
- Pass $polygon as an array of point arrays: `{ $polygon: [[0,0],[3,6],[6,0]] }`
- Convert client map bounds to arrays before querying: `[[w,s],[e,n]]`
- Prefer modern $geoWithin with $geometry (`{ loc: { $geoWithin: { $geometry: { type: 'Polygon', coordinates: [...] } } } }`) — $within is a deprecated legacy operator
Example fix
// before
Model.find({ loc: { $within: { $box: [0, 0, 10, 10] } } });
// after
Model.find({ loc: { $within: { $box: [[0, 0], [10, 10]] } } }); Defensive patterns
Strategy: validation
Validate before calling
function toBoxFilter(w, s, e, n) {
if (![w, s, e, n].every(Number.isFinite)) throw new Error('bounds must be numbers');
return { $within: { $box: [[w, s], [e, n]] } }; // two points, not flattened
} Type guard
function isBoxArg(v) {
return Array.isArray(v) && v.length === 2 && v.every(p => Array.isArray(p) && p.every(Number.isFinite));
} Try / catch
try { await Model.find({ loc: { $within: { $box: box } } }); } catch (err) { if (/Invalid \$within \$box argument/.test(err.message)) { return badRequest('$box needs [[x1,y1],[x2,y2]]'); } throw err; } Prevention
- Convert map-library bounds objects to [[w,s],[e,n]] arrays server-side
- Prefer $geoWithin + $geometry over legacy $within
- Assert two-point shape for $box before querying
When it happens
Trigger: `{ loc: { $within: { $box: [0, 0, 10, 10] } } }` — coordinates flattened into four numbers instead of two points; `{ $polygon: '34,28,35,29' }` (string); `{ $box: [{ x: 0, y: 0 }, { x: 10, y: 10 }] }` (point objects instead of coordinate arrays).
Common situations: Flattening corner coordinates when building map-viewport queries; sending bounding boxes from client map libraries (Leaflet/Google return LatLng objects) without conversion; mixing up $box's two-point contract with $polygon's n-point polygon.
Related errors
- Bad $within parameter: ${JSON.stringify(val)}
- Invalid geoJSON type for $geoWithin "${geoWithinType}", must
- $near must be either an array or an object with a $geometry
- Invalid addFields() argument. Must be an object
- Query filter must be an object, got an array ${util.inspect(
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/b144055e4f77504e.
Report an issue: GitHub.