Automattic/mongoose · error · TypeError
Invalid select() argument. Must be string or object.
Error message
Invalid select() argument. Must be string or object.
What it means
Mongoose's Query.prototype.select() only accepts projections as a string (e.g. 'name -email') or a plain object (e.g. { name: 1, email: 0 }); falsy arguments (0, false, '') return early as a no-op. The argument is run through parseProjection() and only the object branch can produce a projection, so any remaining truthy non-object value falls through to this terminal TypeError. Passing more than one argument triggers a different, earlier error ('Invalid select: select only takes 1 argument'), so this one specifically means a single value of the wrong type.
Source
Thrown at lib/query.js:1203
delete userProvidedFields[field];
}
});
}
});
} else {
const keys = Object.keys(arg);
for (let i = 0; i < keys.length; ++i) {
const value = arg[keys[i]];
const key = keys[i];
fields[key] = sanitizeValue(value);
userProvidedFields[key] = sanitizeValue(value);
}
}
return this;
}
throw new TypeError('Invalid select() argument. Must be string or object.');
};
/**
* Enable or disable schema level projections for this query. Enabled by default.
* Set to `false` to include fields with `select: false` in the query result by default.
*
* #### Example:
*
* const userSchema = new Schema({
* email: { type: String, required: true },
* passwordHash: { type: String, select: false, required: true }
* });
* const UserModel = mongoose.model('User', userSchema);
*
* const doc = await UserModel.findOne().orFail().schemaLevelProjections(false);
*
* // Contains password hash, because `schemaLevelProjections()` overrides `select: false`
* doc.passwordHash;View on GitHub (pinned to 49cdab0136)
Solutions
- Pass a string projection like .select('name email') (prefix a field with - to exclude) or an object like .select({ name: 1, email: 0 })
- If the projection comes from user input, whitelist allowed field names and build the string/object yourself before calling select()
- To clear or no-op the projection, call .select() with no argument or a falsy value
- Check the variable you are passing is not accidentally a number, boolean, or function
Example fix
// before
const users = await User.find().select(1); // TypeError: Invalid select() argument
const users2 = await User.find().select(true); // same TypeError
// after
const users = await User.find().select('name email');
// or
const users2 = await User.find().select({ name: 1, email: 1 }); Defensive patterns
Strategy: type-guard
Validate before calling
const ALLOWED_FIELDS = new Set(['name', 'email', 'age']);
function buildProjection(raw) {
if (raw == null) return undefined;
const fields = (typeof raw === 'string' ? raw.split(/\s+/) : Array.isArray(raw) ? raw : [])
.map(f => f.replace(/^-/, ''))
.filter(f => ALLOWED_FIELDS.has(f));
return fields.length ? fields.join(' ') : undefined;
}
const docs = await Model.find().select(buildProjection(req.query.fields)); Type guard
function isSelectArg(arg) {
return arg == null || typeof arg === 'string' || (typeof arg === 'object' && arg !== null);
} Try / catch
try {
query.select(projection);
} catch (err) {
if (err instanceof TypeError && err.message.includes('select()')) {
throw new Error(`Invalid projection passed to select(): ${JSON.stringify(projection)}`);
}
throw err;
} Prevention
- Whitelist user-supplied projection field names before passing them to select()
- Type projections as string | Record<string, 1 | 0> in TypeScript
- Never pass booleans or numbers to select(); use an explicit spec or omit the call
When it happens
Trigger: .select(1), .select(true), or .select(() => buildFields()); passing an unvalidated request value (req.query.fields) that resolves to a number or boolean; passing a variable that was expected to be a projection object but is actually a primitive.
Common situations: Dynamically building projections from user input without validating shape; passing a boolean or numeric flag where a projection spec belongs; porting code from other ORMs where any truthy value is stringified into a field list.
Related errors
- Invalid addFields() argument. Must be an object
- Invalid sort() argument, must be array of arrays
- Invalid sort() argument. Must be a string, object, array, or
- Options must be an object, got "${options}"
- sort() takes at most 2 arguments
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/c24cb09567ed858c.
Report an issue: GitHub.