Automattic/mongoose · error · TypeError
Collection name must be a string
Error message
Collection name must be a string
What it means
utils.toCollectionName() derives the collection name when registering a model. When a pluralization function is installed (Mongoose's default), the name must be a non-empty string; passing undefined, a number, a class, or any non-string as the model name throws a TypeError.
Source
Thrown at lib/utils.js:56
* Produces a collection name from model `name`. By default, just returns
* the model name
*
* @param {string} name a model name
* @param {Function} pluralize function that pluralizes the collection name
* @return {string} a collection name
* @api private
*/
exports.toCollectionName = function(name, pluralize) {
if (name === 'system.profile') {
return name;
}
if (name === 'system.indexes') {
return name;
}
if (typeof pluralize === 'function') {
if (typeof name !== 'string') {
throw new TypeError('Collection name must be a string');
}
if (name.length === 0) {
throw new TypeError('Collection name cannot be empty');
}
return pluralize(name);
}
return name;
};
/**
* Determines if `a` and `b` are deep equal.
*
* Modified from node/lib/assert.js
*
* @param {any} a a value to compare to `b`
* @param {any} b a value to compare to `a`
* @return {boolean}
* @api privateView on GitHub (pinned to 49cdab0136)
Solutions
- Pass an explicit string name: mongoose.model('User', schema)
- Validate dynamic names before registration: if (typeof name !== 'string' || name.length === 0) throw ...
- Coerce numeric identifiers with String(name) if a numeric-looking name is intended
Example fix
// before mongoose.model(process.env.USER_MODEL, schema); // undefined in env // after const name = process.env.USER_MODEL || 'User'; mongoose.model(name, schema);
Defensive patterns
Strategy: type-guard
Validate before calling
function registerModel(mongoose, name, schema) {
if (typeof name !== 'string' || name.length === 0) throw new TypeError(`Model name must be a non-empty string, got ${typeof name}`);
return mongoose.model(name, schema);
} Type guard
function isValidModelName(name) { return typeof name === 'string' && name.length > 0; } Try / catch
try { mongoose.model(name, schema); } catch (err) { if (/Collection name must be a string/.test(err.message)) throw new Error(`Invalid model name: ${String(name)} (${typeof name})`); throw err; } Prevention
- Default dynamic names explicitly: process.env.MODEL_NAME || 'User'
- Fail fast on unset imports/variables used as model names
- Type model-name parameters as string in TS to catch this at compile time
When it happens
Trigger: mongoose.model(undefined, schema) from an unset variable; mongoose.model(42, schema) with a numeric name; connection.model(SomeClass, schema) passing a class instead of its name; typos like mongoose.model(nane, schema).
Common situations: Dynamic model registration from config files or loops where the name variable is missing or numeric; minified/bundled code where an import resolves to undefined.
Related errors
- Arguments must be aggregate pipeline operators
- Invalid addFields() argument. Must be an object
- Invalid project() argument. Must be string or object
- Invalid `path`. Must be either string or array. Got "${path}
- Cannot set both `validateAllPaths` and `pathsToSkip`
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/5cd5c6437fa4ce0c.
Report an issue: GitHub.