{"record":{"id":"48645d6489631f3f","repo":"Automattic/mongoose","slug":"expected-path-path-to-be-populated","errorCode":null,"errorMessage":"Expected path \"${path}\" to be populated","messagePattern":"Expected path \"(.+?)\" to be populated","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/document.js","lineNumber":5064,"sourceCode":" * @return {Document} this\n * @memberOf Document\n * @method $assertPopulated\n * @instance\n * @api public\n */\n\nDocument.prototype.$assertPopulated = function $assertPopulated(path, values) {\n  if (Array.isArray(path)) {\n    path.forEach(p => this.$assertPopulated(p, values));\n    return this;\n  }\n\n  if (arguments.length > 1) {\n    this.$set(values);\n  }\n\n  if (!this.$populated(path)) {\n    throw new MongooseError(`Expected path \"${path}\" to be populated`);\n  }\n\n  return this;\n};\n\n/**\n * Takes a populated field and returns it to its unpopulated state.\n *\n * #### Example:\n *\n *     Model.findOne().populate('author').exec(function (err, doc) {\n *       console.log(doc.author.name); // Dr.Seuss\n *       console.log(doc.depopulate('author'));\n *       console.log(doc.author); // '5144cf8050f071d979c118a7'\n *     })\n *\n * If the path was not provided, then all populated fields are returned to their unpopulated state.\n *","sourceCodeStart":5046,"sourceCodeEnd":5082,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/document.js#L5046-L5082","documentation":"Document.prototype.$assertPopulated(path, values) is a fail-fast guard: it optionally $set()s the second argument, then throws MongooseError if $populated(path) is falsy, i.e. the path is not currently populated. It exists so code that depends on populated data crashes immediately with a clear path name instead of silently reading raw ObjectId refs.","triggerScenarios":"Calling doc.$assertPopulated('author') after a findOne() that lacked .populate('author'); after doc.$depopulate('author'); after save/depopulate reset the populated state; or with a typo'd path string that was never populated.","commonSituations":"Serializer or view code that assumes a path was populated upstream; a refactor dropped a .populate() call from the query; mixing populate and depopulate flows; nested path names not matching the schema exactly.","solutions":["Populate before asserting: await doc.populate('author') then doc.$assertPopulated('author').","Branch instead of asserting when the path may legitimately be unpopulated: if (doc.$populated('author')) { ... }.","Fix path typos: the path must match the schema path exactly, including full nested paths like 'author.address'.","If you depopulated earlier, re-populate before asserting again."],"exampleFix":"// before\nconst doc = await Model.findOne({ _id: id });\ndoc.$assertPopulated('author'); // throws: query had no .populate()\n\n// after\nconst doc = await Model.findOne({ _id: id }).populate('author');\ndoc.$assertPopulated('author'); // ok\n// or lazily:\nif (!doc.$populated('author')) await doc.populate('author');","handlingStrategy":"validation","validationCode":"async function ensurePopulated(doc, path) {\n  if (!doc.$populated(path)) {\n    await doc.populate(path);\n  }\n  return doc;\n}\n// usage\nawait ensurePopulated(doc, 'author');\ndoc.$assertPopulated('author');","typeGuard":"function isPopulated(doc, path) {\n  return doc.$populated(path) != null;\n}","tryCatchPattern":"try {\n  doc.$assertPopulated('author');\n} catch (err) {\n  if (err instanceof mongoose.MongooseError && err.message.startsWith('Expected path')) {\n    await doc.populate('author'); // populate, then continue\n  } else {\n    throw err;\n  }\n}","preventionTips":["Centralize populate requirements in the query layer so downstream code can assert safely.","Prefer doc.$populated(path) checks where population is optional instead of unconditional asserts.","Test every endpoint that reads populated fields so a dropped .populate() fails CI."],"tags":["mongoose","populate","assertion","unpopulated-path","subdocument"],"backgroundTag":"unpopulated-path-access","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}