{"record":{"id":"8833616738c4d720","repo":"Automattic/mongoose","slug":"invalid-project-argument-must-be-string-or-obje","errorCode":null,"errorMessage":"Invalid project() argument. Must be string or object","messagePattern":"Invalid project\\(\\) argument\\. Must be string or object","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/aggregate.js","lineNumber":264,"sourceCode":"  const fields = {};\n\n  if (typeof arg === 'object' && !Array.isArray(arg)) {\n    Object.keys(arg).forEach(function(field) {\n      fields[field] = arg[field];\n    });\n  } else if (arguments.length === 1 && typeof arg === 'string') {\n    arg.split(/\\s+/).forEach(function(field) {\n      if (!field) {\n        return;\n      }\n      const include = field[0] === '-' ? 0 : 1;\n      if (include === 0) {\n        field = field.substring(1);\n      }\n      fields[field] = include;\n    });\n  } else {\n    throw new MongooseError('Invalid project() argument. Must be string or object');\n  }\n\n  return this.append({ $project: fields });\n};\n\n/**\n * Appends a new custom $group operator to this aggregate pipeline.\n *\n * #### Example:\n *\n *     aggregate.group({ _id: \"$department\" });\n *\n * @see $group https://www.mongodb.com/docs/manual/reference/aggregation/group/\n * @method group\n * @memberOf Aggregate\n * @instance\n * @param {object} arg $group operator contents\n * @return {Aggregate}","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/aggregate.js#L246-L282","documentation":"utils.errorToPOJO() converts an Error instance into a plain object by copying its own enumerable and non-enumerable property names. Because the whole point is to serialize error metadata (stack, message, code) for transport or aggregation, it refuses anything that is not an instanceof Error and throws a plain Error with this message. Mongoose uses it internally when aggregating errors (for example in Model.create() with aggregateErrors and in bulk write error reporting).","triggerScenarios":"Calling utils.errorToPOJO('string') or errorToPOJO({ message: 'x' }) directly; passing a mongoose error-like plain object or an error from another realm/VM (e.g. errors created inside a Jest module registry or vm context fail instanceof Error); libraries that wrap errors as POJOs before Mongoose aggregates them.","commonSituations":"Cross-realm errors in Jest or worker_threads where instanceof fails; user code that normalizes errors to plain objects and then passes them back into an API expecting Error instances; retry wrappers that store err.toJSON() and later feed it to error aggregation.","solutions":["Pass an actual Error instance: errorToPOJO(new Error('...')).","If the value may be a plain object or string, re-wrap it first: typeof x === 'string' || !(x instanceof Error) ? new Error(x) : x.","For cross-realm errors (vm, Jest fake modules), construct errors in the main realm, or duck-type check (x && x.stack && x.message) and wrap."],"exampleFix":"// before\nutils.errorToPOJO({ message: 'boom', code: 42 }); // throws\n\n// after\nconst err = maybeErr instanceof Error ? maybeErr : new Error(String(maybeErr?.message ?? maybeErr));\nconst pojo = utils.errorToPOJO(err);","handlingStrategy":"type-guard","validationCode":"function toErrorPojoSafe(value) {\n  const err = value instanceof Error ? value : new Error(String(value?.message ?? value));\n  return utils.errorToPOJO(err);\n}","typeGuard":"const isErrorLike = (x) =>\n  x instanceof Error || (x != null && typeof x === 'object' && typeof x.stack === 'string' && typeof x.message === 'string');","tryCatchPattern":"try {\n  return utils.errorToPOJO(maybeError);\n} catch (err) {\n  // re-wrap non-Error input and retry once\n  return utils.errorToPOJO(new Error(String(maybeError?.message ?? maybeError)));\n}","preventionTips":["Always pass Error instances across library boundaries; never pre-serialize errors to POJOs.","In Jest/vm/worker contexts, construct errors in the main realm to keep instanceof working.","Duck-type check (message + stack) when receiving errors from other packages and wrap if needed."],"tags":["mongoose","internal","error-handling","typeerror","serialization"],"backgroundTag":"invalid-error-object","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}