#metatype is not a constructor at initialization
24 messages · Page 1 of 1 (latest)
[Nest] 29 - 09/25/2023, 11:04:44 AM LOG [NestFactory] Starting Nest application...
[Nest] 29 - 09/25/2023, 11:04:44 AM LOG [InjectorLogger] Resolving dependency Reflector in the Reflector provider (alias)
[Nest] 29 - 09/25/2023, 11:04:44 AM LOG [InjectorLogger] Looking for Reflector in InternalCoreModule
[Nest] 29 - 09/25/2023, 11:04:44 AM LOG [InjectorLogger] Found Reflector in InternalCoreModule
[Nest] 29 - 09/25/2023, 11:04:44 AM ERROR [ExceptionHandler] metatype is not a constructor
TypeError: metatype is not a constructor
at Injector.instantiateClass (/app/node_modules/@nestjs/core/injector/injector.js:365:19)
at callback (/app/node_modules/@nestjs/core/injector/injector.js:65:45)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Injector.resolveConstructorParams (/app/node_modules/@nestjs/core/injector/injector.js:144:24)
at Injector.loadInstance (/app/node_modules/@nestjs/core/injector/injector.js:70:13)
at Injector.loadProvider (/app/node_modules/@nestjs/core/injector/injector.js:97:9)
at /app/node_modules/@nestjs/core/injector/instance-loader.js:56:13
at async Promise.all (index 0)
at InstanceLoader.createInstancesOfProviders (/app/node_modules/@nestjs/core/injector/instance-loader.js:55:9)
at /app/node_modules/@nestjs/core/injector/instance-loader.js:40:13
at async Promise.all (index 1)
at InstanceLoader.createInstances (/app/node_modules/@nestjs/core/injector/instance-loader.js:39:9)
at InstanceLoader.createInstancesOfDependencies (/app/node_modules/@nestjs/core/injector/instance-loader.js:22:13)
at /app/node_modules/@nestjs/core/nest-factory.js:108:17
at Function.asyncRun (/app/node_modules/@nestjs/core/errors/exceptions-zone.js:22:13)
at NestFactoryStatic.initialize (/app/node_modules/@nestjs/core/nest-factory.js:106:13)
at NestFactoryStatic.createApplicationContext (/app/node_modules/@nestjs/core/nest-factory.js:81:9)
Here is the stack, NEST_DEBUG didn't give me more data
Well, was about to mention the debug env variable, but nevermind
Some context:
I am using INestApplicationContext
yeah, debug added only the two initial infos
Usually this happens when nest is calling new on something that doesn't have a constructor. Come be an invalid custom provider.
If you can provide a link to your git I can take a look
That is a good pointer, I will try to find such an occurance.
Unfortunately it is a commercial closed-source project, can't really share the code 😦
I managed to debug it and see that it blows up on this row: : new metatype(...instances); in injector.js.
I am trying to understand how this thing got there
metatype is something very odd, which is not a class 🙂
it's a Module ?!?
it is something like that:
Module {9: ƒ, id: '/app/node_modules/.../ServiceResolver.js', path: '/app/node_modules/.../providers', exports: {…}, filename: '/app/node_modules/.../providers/ServiceResolver.js', loaded: true, …}
ServiceResolver is a class of mine that I use to wrap around the NestApplicationContext getting of Services
but this class is NOT registered in the container and it is not used by any other class as dependency
here is the code for this class:
export class ServiceResolver<TModule> {
private static applicationCache: Map<any, INestApplicationContext> = new Map<any, INestApplicationContext>();
constructor(protected readonly module:TModule) {}
public async getService<TService>(serviceToken: symbol): Promise<TService> {
const app = await this.getOrCreateApp();
const service = app.get<TService>(serviceToken);
return service;
}
/**
* Resolve a ID Generator.
*
* @param module NestJS module class that satisfies the criteria mentioned above
* @returns An instance of the service
*/
public getIdGenerator(): Promise<IIdGenerator> {
return this.getService<IIdGenerator>(IIdGeneratorToken);
}
private async getOrCreateApp(): Promise<INestApplicationContext> {
let app = ServiceResolver.applicationCache.get(module);
if (app === undefined) {
app = await NestFactory.createApplicationContext(module);
ServiceResolver.applicationCache.set(module, app);
}
return app;
}
}
I use it like that:
export const createIdGenerator = () => new ServiceResolver(MyNestJSModule).getIdGenerator();
when I do that, I get the error
I am stuck, I have no idea why this is trying to be created by the instantiateClass method of Injector
Okay, so I made the methods of ServiceResolver to be static like that:
protected static async getService<TModule, TService>(module: TModule, serviceToken: symbol): Promise<TService> {
const app = await this.getOrCreateApp(module);
const service = app.get<TService>(serviceToken);
return service;
}
private static async getOrCreateApp<TModule>(module: TModule): Promise<INestApplicationContext> {
let app = ServiceResolver.applicationCache.get(module);
if (app === undefined) {
app = await NestFactory.createApplicationContext(module);
ServiceResolver.applicationCache.set(module, app);
}
return app;
}
And I started using it like that:
export const createIdGenerator = () => ServiceResolver.getIdGenerator(ExpenseWorkflowModule);
And the error is now gone and it works again. I am really curious on WHY this was happening. If someone could give me some idea, I think this can either help me NOT do stupid stuff in the future or it might be a bug for Nest?
Hmm, that's really interesting. It seems like somewhere Nest thinks this class is being provided as a module or a provider (both are instantiated to read their metadatas, unless the module is a dynamic module). I'd probably need some sort of reproduction to see what;s happening though