If you’ve worked with NestJS for more than a few hours, you’ve seen this error.
The “Nest can’t resolve dependencies” message is the framework’s way of telling you that its dependency injection system can’t find something it needs. The error is common, but the good news is that it’s almost always one of a handful of causes.
This guide covers the seven most common reasons you’ll encounter this error, with code examples for each. Aaaaaand, I’ll go over why each solution works, so you can avoid the problem in the future rather than just patching symptoms.
Understanding the Error Message
Before diving into solutions, let’s decode what NestJS is actually telling you. Here’s a typical error:
Error: Nest can't resolve dependencies of the UserService (?).
Please make sure that the argument DatabaseService at index [0] is available
in the UserModule context.
Potential solutions:
- Is UserModule a valid NestJS module?
- If DatabaseService is a provider, is it part of the current UserModule?
- If DatabaseService is exported from a separate @Module, is that module
imported within UserModule?
Each part of this message gives you information:
- UserService is the class NestJS is trying to instantiate
- DatabaseService (or
?if it can’t determine the type) is the dependency it can’t find - index [0] means it’s the first parameter in the constructor
- UserModule context tells you which module NestJS is searching in
The error message essentially tells you where to look. Most developers skim past it and start guessing, but reading it carefully often points directly to the problem.
The Seven Causes of Dependency Resolution Errors
These are ordered roughly by how often they occur. Start with the first few before assuming you have a circular dependency problem.
Cause 1: Provider Not in the Module’s Providers Array
This is the most common cause. You created a service, but forgot to register it in any module.
The problem:
// user.module.ts
@Module({
controllers: [UserController],
providers: [], // UserService is missing!
})
export class UserModule {}
// user.controller.ts
@Controller('users')
export class UserController {
constructor(private userService: UserService) {} // Error: can't resolve
}
The fix:
@Module({
controllers: [UserController],
providers: [UserService], // Add the service here
})
export class UserModule {}
This happens when you create a new service file but forget to add it to the module. IDEs will auto-import the class at the top of the file, which makes it feel like you’re done, but NestJS needs the explicit registration in the providers array.
How to check: Search your codebase for the service class name. If it doesn’t appear in any providers array, that’s your problem.
Cause 2: Provider Placed in imports Instead of providers
Services go in providers. Modules go in imports. Mixing them up produces confusing errors.
The problem:
@Module({
imports: [UserService], // Wrong! UserService is not a module
controllers: [UserController],
})
export class UserModule {}
The fix:
@Module({
imports: [], // Only modules go here
controllers: [UserController],
providers: [UserService], // Services go here
})
export class UserModule {}
The giveaway for this mistake is that the error message will show your service name where you’d expect to see a module name. If the error says something like “UserService is not a valid NestJS module,” check your imports array.
Cause 3: Cross-Module Dependency Not Exported
When a service in Module A needs a service from Module B, two things must be true: Module A must import Module B, and Module B must export the service.
The problem:
// auth.module.ts
@Module({
providers: [AuthService], // AuthService exists...
// ...but isn't exported!
})
export class AuthModule {}
// user.module.ts
@Module({
imports: [AuthModule], // AuthModule is imported...
providers: [UserService],
})
export class UserModule {}
// user.service.ts
@Injectable()
export class UserService {
constructor(private authService: AuthService) {} // Error: can't resolve
}
The fix:
// auth.module.ts - add the export
@Module({
providers: [AuthService],
exports: [AuthService], // Now other modules can use it
})
export class AuthModule {}
// user.module.ts - import stays the same
@Module({
imports: [AuthModule],
providers: [UserService],
})
export class UserModule {}
Think of it this way: providers makes a service available within its own module. exports makes it available to modules that import this one. You need both when sharing services across module boundaries.
This is a common source of confusion when setting up NestJS for the first time. The module system is powerful but requires explicit declarations at every boundary.
Cause 4: Circular Dependencies Between Modules
Circular dependencies happen when Module A imports Module B, and Module B imports Module A. NestJS can’t resolve which one to initialize first.
The problem:
// user.module.ts
@Module({
imports: [AuthModule], // UserModule needs AuthModule
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
// auth.module.ts
@Module({
imports: [UserModule], // AuthModule needs UserModule - circular!
providers: [AuthService],
exports: [AuthService],
})
export class AuthModule {}
The fix: Use forwardRef() on both sides:
import { Module, forwardRef } from '@nestjs/common';
// user.module.ts
@Module({
imports: [forwardRef(() => AuthModule)],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
// auth.module.ts
@Module({
imports: [forwardRef(() => UserModule)],
providers: [AuthService],
exports: [AuthService],
})
export class AuthModule {}
The forwardRef() function delays the resolution of the module reference until both modules are defined. It must be used on both sides of the circular relationship.
A word of caution: if you find yourself reaching for forwardRef frequently, it’s usually a sign that your module boundaries need restructuring. See the “When NOT to Use forwardRef” section below.
Cause 5: Circular Dependencies Between Services
Similar to module-level circular dependencies, this happens when Service A injects Service B, and Service B injects Service A.
The problem:
@Injectable()
export class UserService {
constructor(private authService: AuthService) {}
getUser(id: string) {
if (!this.authService.isAuthenticated()) {
throw new UnauthorizedException();
}
// ...
}
}
@Injectable()
export class AuthService {
constructor(private userService: UserService) {} // Circular!
validateUser(email: string) {
return this.userService.findByEmail(email);
}
}
The fix: Use forwardRef() with the @Inject() decorator on both services:
import { Injectable, Inject, forwardRef } from '@nestjs/common';
@Injectable()
export class UserService {
constructor(
@Inject(forwardRef(() => AuthService))
private authService: AuthService,
) {}
}
@Injectable()
export class AuthService {
constructor(
@Inject(forwardRef(() => UserService))
private userService: UserService,
) {}
}
Note that you must use the @Inject() decorator explicitly here. TypeScript’s type inference alone isn’t enough when using forwardRef().
Cause 6: Missing @Injectable() Decorator
NestJS uses the @Injectable() decorator to mark classes that participate in dependency injection. Without it, NestJS doesn’t know how to instantiate the class.
The problem:
// Missing @Injectable() decorator
export class UserService {
constructor(private db: DatabaseService) {}
}
The fix:
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {
constructor(private db: DatabaseService) {}
}
This typically happens when you convert a plain class into a NestJS service, or when you copy code and accidentally remove the decorator. It’s easy to miss because the class looks complete without it.
Cause 7: Testing Module Missing Dependencies
When writing unit tests, the test module needs to provide or mock every dependency that the service under test requires.
The problem:
// user.service.spec.ts
const module = await Test.createTestingModule({
providers: [UserService], // UserService needs DatabaseService!
}).compile();
The fix: Provide mocks for all dependencies:
const module = await Test.createTestingModule({
providers: [
UserService,
{
provide: DatabaseService,
useValue: {
findOne: jest.fn().mockResolvedValue({ id: '1', name: 'Test User' }),
save: jest.fn().mockResolvedValue({ id: '1' }),
delete: jest.fn().mockResolvedValue(undefined),
},
},
],
}).compile();
For Mongoose models, use getModelToken():
import { getModelToken } from '@nestjs/mongoose';
const module = await Test.createTestingModule({
providers: [
UserService,
{
provide: getModelToken(User.name),
useValue: {
find: jest.fn(),
findOne: jest.fn(),
create: jest.fn(),
},
},
],
}).compile();
For TypeORM repositories, use getRepositoryToken():
import { getRepositoryToken } from '@nestjs/typeorm';
const module = await Test.createTestingModule({
providers: [
UserService,
{
provide: getRepositoryToken(User),
useValue: {
find: jest.fn(),
findOne: jest.fn(),
save: jest.fn(),
},
},
],
}).compile();
If you’re working with Prisma, the pattern is similar. I covered Prisma-specific setup in my article on upgrading Prisma in NestJS.
Quick Debugging Checklist
When you encounter this error, run through this checklist:
- [ ] Is the service decorated with
@Injectable()? - [ ] Is the service in
providersarray (notimports)? - [ ] If cross-module: Is the source module in
imports? - [ ] If cross-module: Does the source module
exportthe service? - [ ] Circular dependency? Use
forwardRef()on both sides - [ ] In tests: Are all dependencies provided or mocked?
- [ ] Database models: Using
getModelToken()orgetRepositoryToken()?
Most issues are caught by the first four items. Circular dependencies are less common than people assume.
When NOT to Use forwardRef
forwardRef() solves circular dependency errors, but it’s a bandaid, not a cure. If you’re using it in more than two or three places across your application, that’s a signal that your architecture needs attention.
Signs you’re overusing forwardRef:
- Multiple
forwardRefcalls in the same module - Adding
forwardRefwithout understanding why the circular dependency exists - Circular dependencies that span more than two modules
Better alternatives:
Extract shared logic into a new service. If UserService and AuthService both need the same functionality, maybe that functionality belongs in a third service that both can depend on without circularity.
// Before: UserService <-> AuthService (circular)
// After:
// SharedUserAuthService (new)
// UserService -> SharedUserAuthService
// AuthService -> SharedUserAuthService
Use events to decouple. The @nestjs/event-emitter package (or EventEmitter2) lets services communicate without direct dependencies:
// Instead of AuthService calling UserService directly:
this.eventEmitter.emit('user.validated', { userId, email });
// UserService listens for the event:
@OnEvent('user.validated')
handleUserValidated(payload: { userId: string; email: string }) {
// Handle the event
}
Restructure module boundaries. Sometimes circular dependencies reveal that two modules are too tightly coupled to be separate. Merging them into one module, or extracting their shared concerns into a third module, often produces cleaner architecture.
Visualize your dependencies. Tools like Madge generate visual graphs of your module dependencies and highlight circular references. Seeing the graph often makes the right refactoring obvious.
The goal isn’t to avoid forwardRef entirely—it exists for legitimate edge cases. But if you’re reaching for it regularly, you’re likely accumulating architectural debt that will make the codebase harder to maintain over time.
Conclusion
The “Nest can’t resolve dependencies” error is NestJS telling you that its dependency injection system can’t find something it needs. The fix depends on the cause:
- Most common: Service missing from
providersarray - Cross-module: Need both
importsin the consumer andexportsin the source - Circular dependencies:
forwardRef()works, but refactoring is usually better - Testing: Mock all dependencies using
useValueor token helpers
The error message itself contains useful information—the service it’s trying to create, the dependency it can’t find, and where it’s looking. Reading it carefully often points directly to the problem.
When you do need forwardRef(), use it deliberately and consider whether your module boundaries could be restructured. The short-term fix is easy; the long-term maintainability comes from understanding why the circular dependency exists in the first place.
For more on NestJS architecture and deployment, see my articles on Dockerizing NestJS applications and handling exceptions in TypeScript.