Automattic/mongoose · error · MongooseError
`refPath` must be a string or a function that returns a stri
Error message
`refPath` must be a string or a function that returns a string, got ${inspect(refPath)} What it means
MongooseError raised while $set processes a path with a dynamic `refPath`: to decide whether an assigned populated document matches the ref, Mongoose resolves the refPath option. It must be the string name of a field, or a function that returns a string; a number, undefined, or any other type throws immediately.
Source
Thrown at lib/document.js:1465
}
// Check refPath
let refPath = schema.options.refPath;
if (refPath == null) {
return false;
}
if (typeof refPath === 'function' && !refPath[modelSymbol]) {
let fullPath = path;
const fullPathWithIndexes = this.$__fullPathWithIndexes?.();
if (fullPathWithIndexes?.length) {
fullPath = fullPathWithIndexes + '.' + path;
}
refPath = refPath.call(this, this, fullPath);
}
if (typeof refPath !== 'string') {
throw new MongooseError('`refPath` must be a string or a function that returns a string, got ' + inspect(refPath));
}
const modelName = this.ownerDocument().get(refPath);
return modelName === model.modelName || modelName === model.baseModelName;
})();
let didPopulate = false;
if (refMatches && val instanceof Document && (!val.$__.wasPopulated || utils.deepEqual(val.$__.wasPopulated.value, val._doc._id))) {
const unpopulatedValue = schema?.$isSingleNested ? schema.cast(val, this) : val._doc._id;
this.$populated(path, unpopulatedValue, { [populateModelSymbol]: val.constructor });
val.$__.wasPopulated = { value: unpopulatedValue };
didPopulate = true;
}
let popOpts;
const typeKey = this.$__schema.options.typeKey;
if (schema.options &&
Array.isArray(schema.options[typeKey]) &&View on GitHub (pinned to 49cdab0136)
Solutions
- Make refPath the string name of a field that always contains a model name
- If refPath is a function, guarantee a string return: `function() { return this.type || 'DefaultModel'; }`
- Set the type/discriminator field before assigning or populating the refPath path
- Skip the assignment/populate when the refPath field is missing
Example fix
// before
const schema = new Schema({
type: String,
item: { type: Schema.Types.ObjectId, refPath: function() { return this.type; } } // undefined when type unset
});
doc.item = populatedDoc; // refPath resolved to undefined -> MongooseError
// after
item: { type: Schema.Types.ObjectId, refPath: function() { return this.type || 'Product'; } } Defensive patterns
Strategy: validation
Validate before calling
// Ensure refPath resolves before assigning a populated doc
const st = doc.constructor.schema.path('item');
const rp = st.options.refPath;
const fieldName = typeof rp === 'function' ? rp.call(doc, doc, 'item') : rp;
if (typeof fieldName !== 'string' || typeof doc.get(fieldName) !== 'string') {
throw new Error('refPath does not resolve to a model name; set the type field first');
}
doc.item = populatedDoc; Type guard
function resolvesToModelName(doc, refPathOpt) {
const v = typeof refPathOpt === 'function' ? refPathOpt.call(doc, doc) : refPathOpt;
return typeof v === 'string' && typeof doc.get(v) === 'string';
} Try / catch
try {
doc.item = populatedDoc;
} catch (err) {
if (/refPath` must be a string/.test(err.message)) {
// the discriminator/type field is unset; set it (or a default model) before assigning
} else { throw err; }
} Prevention
- Give the refPath source field an enum and a default so it always resolves
- Prefer a plain string refPath over a function unless the indirection is required
- Set polymorphic type fields before populate() or populated-doc assignment
When it happens
Trigger: A schema option `refPath` set to a non-string (e.g. a number or the field value itself); or a refPath function returning undefined - typically reading a discriminator/type field that is not set - when you then assign a populated document to the path (`doc.item = someDoc`) or populate it.
Common situations: Polymorphic references where the type field is optional or not yet set; refPath functions like `function() { return this.type; }` invoked before the doc has a type; copy-paste mistakes pointing refPath at a data field instead of a model-name field.
Related errors
- Invalid addFields() argument. Must be an object
- Document.prototype.populate() no longer accepts a callback
- Expected path "${path}" to be populated
- For your own good, using `document.save()` to update an arra
- Cast to ${this.instance} failed for value "${value}" (type $
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/df2751d477cd5d6b.
Report an issue: GitHub.