9

I am following the documentation present here

https://docs.nestjs.com/techniques/authentication#jwt-functionality

To have faster support I have created a git repository with the problem

https://github.com/Sano123456/nestjs-jwt

node -v -> v10.15.2
npm -v -> 6.14.6
nest -v -> 7.4.1

First Problem: in AuthModule if I do as described in documentation and just import UserModule, it return me error of circular dependency between UserModule and AuthModule

    @Module({
      imports:[
        UsersModule,
        PassportModule
      ],
      providers: [AuthService],
      controllers: [AuthController],
      exports:[AuthService, LocalStrategy]
    })
    export class AuthModule {}

error:

[ExceptionHandler] Nest cannot create the AuthModule instance.
The module at index [0] of the AuthModule "imports" array is undefined.

Potential causes:
- A circular dependency between modules. Use forwardRef() to avoid it. Read more: https://docs.nestjs.com/fundamentals/circular-dependency
- The module at index [0] is of type "undefined". Check your import statements and the type of the module.

Scope [AppModule -> UsersModule] +6ms

Possibile solution in imports array of AuthModule instead of UserModule put forwardRef(() => UsersModule), this actually remove the error but not sure if this is the right way

Second problem: it says that can't find LocalStrategy class even if it's present and declared in AuthModule

[ExceptionHandler] Nest cannot export a provider/module that is not a part of the currently processed module (AuthModule). Please verify whether the exported LocalStrategy is available in this particular context.Is LocalStrategy part of the relevant providers/imports within AuthModule?

Possibile solution right now I don't have any solution, I just remove it to understand what is the problem

Third problem : after removing LocalStrategy,

[ExceptionHandler] Nest can't resolve dependencies of the AuthService (?). Please make sure that the argument dependency at index [0] is available in the AuthModule context.

Potential solutions:
- If dependency is a provider, is it part of the current AuthModule?
- If dependency is exported from a separate @Module, is that module imported within AuthModule?
  @Module({
    imports: [ /* the Module containing dependency */ ]
  })
 +1ms
Error: Nest can't resolve dependencies of the AuthService (?). Please make sure that the argument dependency at index [0] is available in the AuthModule context.

anyone solved this issues?

Sano
  • 469
  • 2
  • 6
  • 21

3 Answers3

25

You have a circular dependancy because your UsersModule and your AuthModule import each other. Therefore you have 2 options to repair this issue.

The first is to make a forward reference which will allow both modules to be built simultaneously and once built, pass in the reference required. This is done like so:

@Module({
  imports: [
    forwardRef(() => UsersModule),
  ],
  ...
})
export class AuthModule {}

// And the same for your UsersModule

@Module({
  imports: [
    forwardRef(() => AuthModule),
  ],
})
export class UsersModule {}

The second option is to remove the dependancies from one another. This is not always possible and guessing by the names of your modules I would argue this isn't possible. You don't want to have the auth module accessing the user module's database and services etc outside the users module. But I'll give you some advice on module inheritance.

Module in nestjs are built asynchronously. Meaning they have to be structured like a cascading tree with one module importing all the others. Something linear will look like this

AppModule <= CatModule <= PawsModule

Another example would be dual importing

            <= CatModule
AppModule                  <= PawsModule
            <= DogModule 

In the above example, the paws module is created once and imported in both cat and dog module. Meaning paws module will be built first before cat and dog module.

So to explain your error you need to think from a linear code perspective and how the module import tree will share modules that import each other. Because they import each other, nest can't decide which to create first so will need a reference to pass back, hence the function. I've always imagined the container's forward ref function as saying "Hey, hold this for a sec" (it's a piece of paper that says "UsersModule") then turns around, does some wavey of the arms with his back turned, then turns around and replaces the piece of paper with the UsersModule!

Your second issue is you never created a provider for LocalStrategy. It doesn't exist in the AuthModule so cannot be imported into AuthService nor exported from AuthModule!

bashleigh
  • 8,813
  • 5
  • 29
  • 49
13

** SOLUTION of problem "can't resolve dependencies" **

For the first and second problem the final solution is to use @Inject(forwardRef(() => AuthService)) in UserService here is example

@Injectable()
export class UserService {
    constructor(
        @InjectRepository(User) private readonly UserRepository: Repository<User>,
        private readonly config: ConfigService,
        @Inject(forwardRef(() => AuthService)) //<--- 
        private readonly authService: AuthService,
    ) {
        
    }

Same thing also in AuthService

@Injectable()
export class AuthService {
  private client: any;
  constructor(
    @Inject(forwardRef(() => UserService))//<--- here
    private readonly userService: UserService,
    @InjectConfig() private readonly config,
  ) {
  }

In AuthModule and UserModule you need to still use forwardRef

I never used this solution before and i never needed it, but this solved my issue

Regarding LocalStrategy, put it in providers array of the module

Sano
  • 469
  • 2
  • 6
  • 21
5

For me, it wasn't enough to just use the forwardRef on both services as in Sano's answer; I also had to forwardRef on both circular dependent modules too.

In both services:

https://docs.nestjs.com/fundamentals/circular-dependency#forward-reference

import { forwardRef, Inject } from '@nestjs/common';
...
@Inject(forwardRef(() => UserService))`

In both modules:

https://docs.nestjs.com/fundamentals/circular-dependency#module-forward-reference

import { forwardRef } from '@nestjs/common';
...
imports: [
   forwardRef(() => UsersModule),
],
Robert Rendell
  • 1,658
  • 15
  • 18
  • if you are using forwardRef in both services and modules, means there is an error in you module architecture – Sano Aug 05 '22 at 12:49
  • Yes! We came to the same conclusion and ended up adding more models to our architecture to properly solve our forwardRef issue. – Robert Rendell Aug 11 '22 at 09:52