Automattic/mongoose · warning · MongooseError
Aggregate `near()` must be called with non-nullish argument
Error message
Aggregate `near()` must be called with non-nullish argument
What it means
When a schema path is added, Mongoose checks whether the FIRST segment of the dotted path collides with a reserved name on the Document prototype (save, errors, schema, on, once, emit, get, set, init, isNew, toObject, toJSON, ...). Because these become properties/methods on every document, a user path with the same name shadows them and can break Mongoose internals. Since Mongoose 5 this is only a warning (utils.warn), not an exception; special properties like $.foo still throw, but reserved names just warn unless suppressed.
Source
Thrown at lib/aggregate.js:410
* maxDistance: 0.008,
* query: { type: "public" },
* includeLocs: "dist.location",
* spherical: true,
* });
*
* @see $geoNear https://www.mongodb.com/docs/manual/reference/aggregation/geoNear/
* @method near
* @memberOf Aggregate
* @instance
* @param {object} arg
* @param {object|number[]} arg.near GeoJSON point or coordinates array
* @return {Aggregate}
* @api public
*/
Aggregate.prototype.near = function(arg) {
if (arg == null) {
throw new MongooseError('Aggregate `near()` must be called with non-nullish argument');
}
if (arg.near == null) {
throw new MongooseError('Aggregate `near()` argument must have a `near` property');
}
const coordinates = Array.isArray(arg.near) ? arg.near : arg.near.coordinates;
if (typeof arg.near === 'object' && (!Array.isArray(coordinates) || coordinates.length < 2 || coordinates.find(c => typeof c !== 'number'))) {
throw new MongooseError(`Aggregate \`near()\` argument has invalid coordinates, got "${coordinates}"`);
}
const op = {};
op.$geoNear = arg;
return this.append(op);
};
/*!
* define methods
*/
View on GitHub (pinned to 49cdab0136)
Solutions
- Rename the path to something non-reserved, e.g. 'save' -> 'isSaved', 'on' -> 'activeAt', 'errors' -> 'validationIssues' (you can keep the MongoDB key different using the 'alias' option or a virtual).
- If the collision is intentional and tested, silence it per schema: new Schema({...}, { suppressReservedKeysWarning: true }).
- Use field aliases to keep the stored key: { errors: { type: String, alias: 'docErrors' } } and access doc.docErrors.
- Audit usages of doc.toObject()/JSON serialization after renaming to make sure API consumers are updated.
Example fix
// before
const schema = new Schema({ on: Date, errors: [String] }); // warns
// after
const schema = new Schema({
activeAt: { type: Date, alias: 'on' },
issues: { type: [String], alias: 'errors' }
}); Defensive patterns
Strategy: validation
Validate before calling
const RESERVED = new Set(['save','errors','schema','on','once','emit','init','get','set','isNew','toObject','toJSON','populate','remove','deleteOne','updateOne','overwrite','collection','db','model','$__']);
function assertSafePaths(definition) {
for (const key of Object.keys(definition)) {
if (RESERVED.has(key.split('.')[0])) {
throw new Error(`Field "${key}" collides with a reserved Document name; rename it or use suppressReservedKeysWarning`);
}
}
} Prevention
- Run a schema-definition lint step in CI that flags reserved first-segment path names.
- Prefer aliases for API compatibility instead of storing reserved keys.
- Review the reserved list in the Mongoose docs when adding fields to shared/base schemas.
When it happens
Trigger: Defining new Schema({ errors: String }), { save: Boolean }, { on: Date }, { schema: Mixed }, or a nested first segment like 'init.name' in the schema definition; also indirect definitions via schema.add({ ... }) or a nested path whose first piece is reserved.
Common situations: Logging/event schemas that naturally want a field named 'on' or 'init'; audit schemas with an 'errors' array; migrating a MongoDB collection whose documents contain keys that collide with Document methods; ORM-agnostic code reused across libraries where the same field name is fine elsewhere.
Related errors
- Invalid arg "${arg}" to unwind(), must be string or object
- Invalid sort() argument. Must be a string or object.
- If thenExpr or elseExpr is string, it must be either $$DESCE
- Invalid arg "${arg}" to sortByCount(), must be string or obj
- Invalid graphLookup() argument. Must be an object.
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/9dcfc48db9e81a9f.
Report an issue: GitHub.