Bug Report: ObjectId constructor invoked without 'new' keyword causes TypeError
Description
When using @nestjs-query/query-mongoose with Mongoose 9.x, filtering by _id field throws a TypeError: Class constructor ObjectId cannot be invoked without 'new'.
Environment
- @nestjs-query/query-mongoose: 0.30.0
- mongoose: 9.1.2
- @nestjs/mongoose: 11.0.4
- Node.js: v22.x (or your version)
Steps to Reproduce
- Set up NestJS Query with Mongoose
- Define a DTO with
@IDField() or @FilterableField() for _id field
- Execute a GraphQL query with filter on
_id:
query {
parks(filter: { _id: { eq: "b0000000000000000000000a" } }) {
edges {
node {
_id
name
}
}
}
}
Error Stack Trace
TypeError: Class constructor ObjectId cannot be invoked without 'new'
at ComparisonBuilder.convertToObjectId (/node_modules/@nestjs-query/query-mongoose/src/query/comparison.builder.ts:123:22)
at ComparisonBuilder.convertQueryValue (/node_modules/@nestjs-query/query-mongoose/src/query/comparison.builder.ts:112:19)
at ComparisonBuilder.build (/node_modules/@nestjs-query/query-mongoose/src/query/comparison.builder.ts:59:51)
at WhereBuilder.withFilterComparison (/node_modules/@nestjs-query/query-mongoose/src/query/where.builder.ts:74:37)
Root Cause
In comparison.builder.js (line 82 in compiled version, line 123 in TypeScript source), the ObjectId constructor is called without the new keyword.
Current code (line 82 in dist/src/query/comparison.builder.js):
return mongoose_1.Types.ObjectId(val);
Should be:
return new mongoose_1.Types.ObjectId(val);
In modern JavaScript/TypeScript, class constructors like ObjectId must be invoked with the new keyword. Mongoose 9.x enforces this requirement strictly, whereas older versions may have been more lenient.
Temporary Workaround
Until this is fixed in the package, you can temporarily patch the compiled file:
- Navigate to
node_modules/@nestjs-query/query-mongoose/dist/src/query/comparison.builder.js
- Find line 82 in the
convertToObjectId method
- Change:
return mongoose_1.Types.ObjectId(val);
To:
return new mongoose_1.Types.ObjectId(val);
Note: This workaround will be lost when reinstalling dependencies. Consider using a patch tool like patch-package to persist this fix.
Proposed Fix
Update src/query/comparison.builder.ts line 123 in the source code:
// Before
private convertToObjectId(val: string | number | (string | number)[]): any {
if (Array.isArray(val)) {
return val.map((v) => this.convertToObjectId(v));
}
if (typeof val === 'string' || typeof val === 'number') {
if (Types.ObjectId.isValid(val)) {
return Types.ObjectId(val); // ❌ Missing 'new' keyword
}
}
return val;
}
// After
private convertToObjectId(val: string | number | (string | number)[]): any {
if (Array.isArray(val)) {
return val.map((v) => this.convertToObjectId(v));
}
if (typeof val === 'string' || typeof val === 'number') {
if (Types.ObjectId.isValid(val)) {
return new Types.ObjectId(val); // ✅ Added 'new' keyword
}
}
return val;
}
Additional Context
- This appears to be a regression or incompatibility with Mongoose 9.x where
ObjectId constructor must be called with the new keyword
- The issue occurs specifically when filtering on ObjectId fields (typically
_id or other fields with @Prop({ type: Types.ObjectId }))
- Other filtering operations on non-ObjectId fields work correctly
- This likely affects all users running Mongoose 9.x with @nestjs-query/query-mongoose 0.30.0
- The same pattern may exist in other parts of the codebase that instantiate ObjectId
Expected Behavior
Filtering by _id field (or any ObjectId field) should work without throwing TypeError. The query should execute successfully and return filtered results:
{
"data": {
"parks": {
"edges": [
{
"node": {
"_id": "b0000000000000000000000a",
"name": "Park Name"
}
}
]
}
}
}
Actual Behavior
TypeError is thrown when attempting to filter by _id field, preventing any ObjectId-based filtering operations. The GraphQL query fails completely with:
TypeError: Class constructor ObjectId cannot be invoked without 'new'
This makes it impossible to filter documents by their ObjectId fields, which is a critical feature for MongoDB-based applications.
Bug Report: ObjectId constructor invoked without 'new' keyword causes TypeError
Description
When using
@nestjs-query/query-mongoosewith Mongoose 9.x, filtering by_idfield throws aTypeError: Class constructor ObjectId cannot be invoked without 'new'.Environment
Steps to Reproduce
@IDField()or@FilterableField()for_idfield_id:Error Stack Trace
Root Cause
In
comparison.builder.js(line 82 in compiled version, line 123 in TypeScript source), theObjectIdconstructor is called without thenewkeyword.Current code (line 82 in dist/src/query/comparison.builder.js):
Should be:
In modern JavaScript/TypeScript, class constructors like
ObjectIdmust be invoked with thenewkeyword. Mongoose 9.x enforces this requirement strictly, whereas older versions may have been more lenient.Temporary Workaround
Until this is fixed in the package, you can temporarily patch the compiled file:
node_modules/@nestjs-query/query-mongoose/dist/src/query/comparison.builder.jsconvertToObjectIdmethodNote: This workaround will be lost when reinstalling dependencies. Consider using a patch tool like
patch-packageto persist this fix.Proposed Fix
Update
src/query/comparison.builder.tsline 123 in the source code:Additional Context
ObjectIdconstructor must be called with thenewkeyword_idor other fields with@Prop({ type: Types.ObjectId }))Expected Behavior
Filtering by
_idfield (or any ObjectId field) should work without throwing TypeError. The query should execute successfully and return filtered results:{ "data": { "parks": { "edges": [ { "node": { "_id": "b0000000000000000000000a", "name": "Park Name" } } ] } } }Actual Behavior
TypeError is thrown when attempting to filter by
_idfield, preventing any ObjectId-based filtering operations. The GraphQL query fails completely with:This makes it impossible to filter documents by their ObjectId fields, which is a critical feature for MongoDB-based applications.