You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
tl;dr: Nested DynamicModules fail to inject dependencies / resolve providers correctly when using LazyModuleLoader.
Current behavior
Consider having 3 modules: ConfigModule, ModuleA and ModuleB. ModuleA and ModuleB have static functions to create DynamicModules, where ModuleA depends on ModuleB and imports it.
When loading ModuleA from ConfigModule via a LazyModuleLoader, the dependencies of ModuleA (in that case the providers of ModuleB) seem not to be injected, resulting in the following message:
throw new unknown_dependencies_exception_1.UnknownDependenciesException(wrapper.name, dependencyContext, moduleRef);
^
Error: Nest can't resolve dependencies of the TOKENA (?). Please make sure that the argument SomeClassB at index [0] is available in the ModuleA context.
Potential solutions:
- If SomeClassB is a provider, is it part of the current ModuleA?
- If SomeClassB is exported from a separate @Module, is that module imported within ModuleA?
@Module({
imports: [ /* the Module containing SomeClassB */ ]
})
at Injector.lookupComponentInParentModules (/Downloads/nestjs-nested-dynamic-module-reproduction/node_modules/@nestjs/core/injector/injector.js:193:19)
at Injector.resolveComponentInstance (~/Downloads/nestjs-nested-dynamic-module-reproduction/node_modules/@nestjs/core/injector/injector.js:149:33)
at resolveParam (~/Downloads/nestjs-nested-dynamic-module-reproduction/node_modules/@nestjs/core/injector/injector.js:103:38)
at async Promise.all (index 0)
at Injector.resolveConstructorParams (~/Downloads/nestjs-nested-dynamic-module-reproduction/node_modules/@nestjs/core/injector/injector.js:118:27)
at Injector.loadInstance (~/Downloads/nestjs-nested-dynamic-module-reproduction/node_modules/@nestjs/core/injector/injector.js:47:9)
at Injector.loadProvider (~/Downloads/nestjs-nested-dynamic-module-reproduction/node_modules/@nestjs/core/injector/injector.js:69:9)
at async Promise.all (index 3)
at InstanceLoader.createInstancesOfProviders (~/Downloads/nestjs-nested-dynamic-module-reproduction/node_modules/@nestjs/core/injector/instance-loader.js:44:9)
at ~/Downloads/nestjs-nested-dynamic-module-reproduction/node_modules/@nestjs/core/injector/instance-loader.js:29:13
For clarification: My goal is to conditionally load different modules based on the instantiated ConfigService. So maybe this approach is not ideal, but the best one I could come up with.
The exported providers of the dynamic module ModuleB should be injected successfully into ModuleA.
Possible Solution
It seems that in packages/core/injector/container.ts the function addModule is called multiple times for ModuleB when lazily loading the module, thus returning undefined in line 69 on subsequent calls.
In combination with the scanForModules and insertModule functions from packages/core/scanner.ts, which will be called from the LazyModuleLoader this seems to have the effect, that the returned moduleRef is undefined and the dependencies won't get resolved correctly due to line 129f.
diff --git a/packages/core/injector/container.ts b/packages/core/injector/container.ts
index e01336a..c1355bf 100644
--- a/packages/core/injector/container.ts+++ b/packages/core/injector/container.ts@@ -56,7 +56,7 @@ export class NestContainer {
public async addModule(
metatype: Type<any> | DynamicModule | Promise<DynamicModule>,
scope: Type<any>[],
- ): Promise<Module | undefined> {+ ): Promise<Module> {
// In DependenciesScanner#scanForModules we already check for undefined or invalid modules
// We still need to catch the edge-case of `forwardRef(() => undefined)`
if (!metatype) {
@@ -66,7 +66,7 @@ export class NestContainer {
metatype,
);
if (this.modules.has(token)) {
- return;+ return this.modules.get(token);
}
const moduleRef = new Module(type, this);
moduleRef.token = token;
Environment
Nest version: 8.0.6
(So this seems to be an issue in the latest Nest version, too.)
For Tooling issues:
- Node version: v16.6.2
- Platform: Mac
Others:
yarn is used as package manager.
The text was updated successfully, but these errors were encountered:
I am running into an exact same problem as the above issue, where I have a DynamicModule with a controller inside that is trying to inject ModuleRef. And I got an dependency error where the ModuleRef was not injected properly.
I can try to create a minimum reproduction here, but right now I am downgrading to NestJS v7 and it seems to be working.
Bug Report
tl;dr: Nested
DynamicModule
s fail to inject dependencies / resolve providers correctly when usingLazyModuleLoader
.Current behavior
Consider having 3 modules:
ConfigModule
,ModuleA
andModuleB
.ModuleA
andModuleB
have static functions to createDynamicModule
s, whereModuleA
depends onModuleB
and imports it.When loading
ModuleA
fromConfigModule
via aLazyModuleLoader
, the dependencies ofModuleA
(in that case the providers ofModuleB
) seem not to be injected, resulting in the following message:For clarification: My goal is to conditionally load different modules based on the instantiated
ConfigService
. So maybe this approach is not ideal, but the best one I could come up with.Input Code
I created a small reproduction repository here: https://github.com/felix-gohla/nestjs-nested-dynamic-module-reproduction.
You can see that this does not happen when importing
ModuleA
directly in theAppModule
and not via the config module.Expected behavior
The exported providers of the dynamic module
ModuleB
should be injected successfully intoModuleA
.Possible Solution
It seems that in packages/core/injector/container.ts the function
addModule
is called multiple times forModuleB
when lazily loading the module, thus returningundefined
in line 69 on subsequent calls.In combination with the
scanForModules
andinsertModule
functions from packages/core/scanner.ts, which will be called from theLazyModuleLoader
this seems to have the effect, that the returnedmoduleRef
is undefined and the dependencies won't get resolved correctly due to line 129f.Modifying
packages/core/injector/container.ts:addModule
to return the module, seems to fix the issue. But I'm not sure, what this could break:Environment
The text was updated successfully, but these errors were encountered: