141

I've got a PlayersModule and an ItemsModule.

I want to use the ItemsService in the PlayersService.

When I add it by injection:

import { Injectable } from '@nestjs/common';
import { InjectModel } from 'nestjs-typegoose';
import { ModelType, Ref } from 'typegoose';
import { Player } from './player.model';
import { Item } from '../items/item.model';
import { ItemsService } from '../items/items.service';

@Injectable()
export class PlayersService {
    constructor(
        @InjectModel(Player) private readonly playerModel: ModelType<Player>,
        private readonly itemsService: ItemsService){}

I get this nest error :

[Nest] 11592 - 2018-8-13 11:42:17 [ExceptionHandler] Nest can't resolve dependencies of the PlayersService (+, ?). Please make sure that the argument at index [1] is available in the current context.

Both modules are imported in the app.module.ts. Both services are working alone in their module.

Kim Kern
  • 54,283
  • 17
  • 197
  • 195
Fairydhwen
  • 1,595
  • 3
  • 11
  • 10

9 Answers9

344

You have to export the ItemsService in the module that provides it:

@Module({
  controllers: [ItemsController],
  providers: [ItemsService],
  exports: [ItemsService]
  ^^^^^^^^^^^^^^^^^^^^^^^
})
export class ItemsModule {}

and then import the exporting module in the module that uses the service:

@Module({
  controllers: [PlayersController],
  providers: [PlayersService],
  imports: [ItemsModule]
  ^^^^^^^^^^^^^^^^^^^^^^
})
export class PlayersModule {}

⚠️ Don't add the same provider to multiple modules. Export the provider, import the module. ⚠️

Kim Kern
  • 54,283
  • 17
  • 197
  • 195
  • Ok, thanks you. So i have to import ItemsModule into PlayersModule even if it is already known by AppModule ? – Fairydhwen Aug 13 '18 at 12:15
  • If you want to use it in the PlayersModule, yes. – Kim Kern Aug 13 '18 at 12:16
  • 2
    I used @KimKern 's suggestion, still see the errors that the injected service is not recognized. – Liangjun Apr 12 '19 at 18:57
  • @Liangjun There are also other reasons why a dependency can not be injected. You can always open a new question. – Kim Kern Apr 12 '19 at 19:01
  • I actually had the problem solved by just restarting my Visual Studio Code. strange. Thanks. – Liangjun Apr 20 '19 at 02:32
  • 6
    Was trying to import the Service itself, turned out importing the module itself worked. Thank you – Nasta Apr 29 '19 at 16:36
  • 3
    @nasta did you still need to additionally import the service inside PlayersService? i.e. `import { ItemsService } from '../items/items.service';`. In addition, is there some kind of decorator we use here inside the constructor? `@Inject private readonly itemsService: ItemsService` – baku Jun 11 '19 at 00:31
  • 1
    @baku Yes, you need the js import. See this answer https://stackoverflow.com/a/51516526/4694994 – Kim Kern Jun 11 '19 at 07:39
  • Currently this won't work... You will still need to add ItemsService in the providers of the providers array of the PlayersModule – Omar Hossam Ahmed Apr 02 '20 at 14:27
  • @OmarHossamAhmed You should not add the `ItemsService` to the `PlayersModule`. Did you export the `ItemsService` in the `ItemsModule` before importing it in the `PlayersModule`? – Kim Kern Apr 02 '20 at 16:54
  • Yes I was working on something similar and it only seemed to work when I added it in the providers module. It was a service registered in module x and exported by said module. Now, the weirdest thing I tried it again now and it worked! Sorry for my false information, but I noticed some weird behaviour with dependency injection lately., – Omar Hossam Ahmed Apr 02 '20 at 19:38
  • Hi Kim Kern. This works perfect sir. I had one problem. I want to share the TypeOrm repository from one module to other. I tried this in case of Repository but it didn't work. – Sushant Keni Apr 07 '20 at 16:47
  • @SushantKeni Thanks, I'm glad this answer is helpful. :-) It's difficult to answer your question without seeing your code. Consider opening a new question for it and include the relevant code snippets. – Kim Kern Apr 07 '20 at 17:19
  • Is it possible to have a service class without @Injectable annotattion, and also this class does not belong to any module?, I saw an example like that, where this service belongs to a commons folder, and it was registered in another module in the the providers array, and it injected in other service's constructor method – Hector Jan 18 '21 at 16:45
  • 1
    @Hector I am not sure I understood your use case fully, but I had these two thoughts: You can define regular JS classes outside of nests application container and then just create them where you need them (-> no injection possible). Also, there are global modules, that only need to be imported once (also see https://stackoverflow.com/a/55181002/4694994). If this does not help, consider opening a new question and add more details to it, ideally a minimal code snippet explaining your scenario. – Kim Kern Jan 19 '21 at 19:50
  • If you get into circular. Use `forwardRef`, https://docs.nestjs.com/fundamentals/circular-dependency – Jeremy Rajan Jun 27 '21 at 05:46
  • My mistake was not adding `@` before `Module` decorator and `nest.js` didn't complain about this – Pranoy Sarkar Aug 30 '22 at 07:39
  • after trying this solution out I keep getting an error `Error: Cannot find module 'src/item/item.service'` the app I'm working on has an `app.module.ts` which imports both modules. could that be the issue? – Fazwelington Sep 12 '22 at 20:31
  • Thanks, alghough this is terrible...It would have been nicer to have a "ModuleWithProviders" to use in the root and then share providers. It doesn't make much sense to me exporting a service...in Angular export is mostly for Components and Modules...Providers are handled differently! Or at least, I never exported a provider in Angular... Thanks a lot by the way, it worked! – OtaconKiko Sep 16 '22 at 15:41
  • This helped me ... Thanks. Was pulling my hair out before I read this answer :) – iam thadiyan Jun 21 '23 at 10:26
34

Let' say you want to use AuthService from AuthModule in my TaskModule's controller

for that, you need to export authService from AuthModule

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

then in TaskModule, you need to import AuthModule (note: import AuthModule not the AuthService in TaskModule)

@Module({
    imports:[
      AuthModule
    ],
    controllers: [TasksController],
    providers: [TasksService]
  })
export class TasksModule {}

Now you should be able to use DI in TaskController

@Controller('tasks')
export class TasksController {
   constructor(private authService: AuthService) {}
   ...
}
  
Hugo
  • 1,106
  • 15
  • 25
santonil2003
  • 476
  • 4
  • 3
14

The question is answered by Kim Kern. But I just want to remind people who read through this comment. Whenever you get this error, you should follow these steps that may help you easily figure out where the stuck is:

  • Make sure the Module which provides providers was imported.
  • Make sure the provider which you are using is exported.

For example, you have category module which contains category service, post module has post service and it has category service as a dependency:

@Module({
    controllers: [CategoryController],
    providers: [CategoryService],
    exports: [CategoryService] // Remember to export
  })
export class CategoryModule {}

And

@Module({
    imports: [CategoryModule], // Make sure you imported the module you are using
    controllers: [PostController],
    providers: [PostService]
  })
export class PostModule {}

Don't forget to use this annotation. Nest uses this to detect singleton class. In spring boot - Java, this one used to be called Bean. Read more:

@Injectable()  
export class PostService {
  constructor(private readonly categoryService: CategoryService // This will be auto injected by Nestjs Injector) {}
}
Justin Dang
  • 234
  • 3
  • 7
5

I solved my problem by removing @Inject() from the argument in my constructor that was passing the exported service.

peterjah
  • 11
  • 3
Ben Stickley
  • 1,551
  • 1
  • 16
  • 22
3

I believe that you faced the same problem i had. My scenario was 2 sibling custom modules (user, auth) that needed to use each other's services. I used circular DI to solve it. please check this link

Let me know whether if it solved your issue, maybe I can advise you further.

Yousuf Khan
  • 334
  • 3
  • 12
Eyal Israel
  • 257
  • 4
  • 9
  • I thought this problem just because services didn't export, it's different from Angular. – LiHao Mar 21 '21 at 03:19
1

Based on the answer by Kim Kern nowadays we should add only injected service into our service without any decorators (@Inject() doesn't required). After that it will work right. That was my mistake and probably can help others.

Ivan Efremov
  • 151
  • 1
  • 4
0

Solved my problem by changing the way of importing the constant string (TOKEN) used in @Inject()) of my provider... be careful using index.ts whith export * from module.ts, nest won't resolve the dependecy

peterjah
  • 11
  • 3
-1

Steps 1. Export the file that you want Step 2. Import the whole module.

I initially made a mistake of adding the file as provider and also adding the module which was throwing error.

PKS
  • 618
  • 1
  • 7
  • 19
-1

None of the responses worked for me. Until I changed the constructor of my using/importing service from:

constructor(private usersService: UsersService) {}

to:

constructor(@Inject(UsersService) private usersService: UsersService) {}
            ^^^^^^^^^^^^^^^^^^^^^

Of course you have to import Inject, and UsersService