debug:nestjs

NestJS Debugging Guide

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "debug:nestjs" with this command: npx skills add snakeo/claude-debug-and-refactor-skills-plugin/snakeo-claude-debug-and-refactor-skills-plugin-debug-nestjs

NestJS Debugging Guide

This guide provides a systematic approach to debugging NestJS applications. Use the four-phase methodology below to efficiently identify and resolve issues.

Common Error Patterns

  1. Dependency Resolution Errors

Error Message:

Nest can't resolve dependencies of the <ProviderName> (?). Please make sure that the argument <DependencyName> at index [0] is available in the <ModuleName> context.

Common Causes:

  • Provider not added to module's providers array

  • Missing @Injectable() decorator on service class

  • Incorrect import/export between modules

  • Typo in injection token name

  • Missing forRoot() /forRootAsync() configuration

Solutions:

// Ensure provider is in the module @Module({ providers: [MyService], // Add missing provider here exports: [MyService], // Export if used by other modules }) export class MyModule {}

// Ensure @Injectable() decorator exists @Injectable() export class MyService { constructor(private readonly dependency: OtherService) {} }

// For external modules, import the module not just the service @Module({ imports: [OtherModule], // Import the module }) export class MyModule {}

  1. Circular Dependency Errors

Error Message:

Nest cannot create the module instance. The module at index [X] of the imports array is undefined.

Common Causes:

  • Two modules importing each other

  • Two services depending on each other

  • File-level circular imports (constants, types)

Solutions:

// Use forwardRef() for circular module dependencies @Module({ imports: [forwardRef(() => OtherModule)], }) export class MyModule {}

// Use forwardRef() for circular service dependencies @Injectable() export class ServiceA { constructor( @Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB, ) {} }

// Alternative: Extract shared logic to a third module @Module({ providers: [SharedService], exports: [SharedService], }) export class SharedModule {}

  1. Guard/Interceptor Issues

Error Message:

Cannot read property 'canActivate' of undefined Cannot read property 'intercept' of undefined

Common Causes:

  • Guard/Interceptor not properly registered

  • Missing @UseGuards() or @UseInterceptors() decorator

  • Incorrect scope (request-scoped vs singleton)

  • Dependencies not available in guard/interceptor context

Solutions:

// Register globally in main.ts app.useGlobalGuards(new AuthGuard()); app.useGlobalInterceptors(new LoggingInterceptor());

// Or register via module for DI support @Module({ providers: [ { provide: APP_GUARD, useClass: AuthGuard, }, { provide: APP_INTERCEPTOR, useClass: LoggingInterceptor, }, ], }) export class AppModule {}

// Controller-level registration @UseGuards(AuthGuard) @UseInterceptors(LoggingInterceptor) @Controller('users') export class UsersController {}

  1. Pipe Validation Errors

Error Message:

An instance of an invalid class-validator value was provided Validation failed (expected type)

Common Causes:

  • Missing class-transformer or class-validator packages

  • DTO not properly decorated with validation decorators

  • ValidationPipe not configured correctly

  • Transform option not enabled

Solutions:

// Enable ValidationPipe globally with proper options app.useGlobalPipes( new ValidationPipe({ whitelist: true, // Strip non-whitelisted properties forbidNonWhitelisted: true, // Throw on extra properties transform: true, // Auto-transform payloads to DTO instances transformOptions: { enableImplicitConversion: true, }, }), );

// Properly decorate DTOs import { IsString, IsInt, Min, IsOptional } from 'class-validator'; import { Type } from 'class-transformer';

export class CreateUserDto { @IsString() name: string;

@IsInt() @Min(0) @Type(() => Number) age: number;

@IsOptional() @IsString() email?: string; }

  1. Microservice Communication Errors

Error Message:

There is no matching message handler defined in the remote service Connection refused / ECONNREFUSED

Common Causes:

  • Message pattern mismatch between client and server

  • Transport configuration mismatch

  • Service not connected or not running

  • Serialization/deserialization issues

Solutions:

// Ensure matching patterns // Server side @MessagePattern({ cmd: 'get_user' }) async getUser(data: { id: number }) { return this.usersService.findOne(data.id); }

// Client side - pattern must match exactly const user = await this.client.send({ cmd: 'get_user' }, { id: 1 }).toPromise();

// Check transport configuration matches // Server const app = await NestFactory.createMicroservice<MicroserviceOptions>( AppModule, { transport: Transport.TCP, options: { host: '0.0.0.0', port: 3001 }, }, );

// Client module ClientsModule.register([ { name: 'USER_SERVICE', transport: Transport.TCP, options: { host: 'localhost', port: 3001 }, }, ]);

  1. WebSocket/Gateway Errors

Error Message:

Gateway is not defined WebSocket connection failed

Common Causes:

  • Missing @WebSocketGateway() decorator

  • Gateway not added to module providers

  • CORS issues with WebSocket connections

  • Adapter not properly configured

Solutions:

// Properly configure gateway @WebSocketGateway({ cors: { origin: '*', }, namespace: '/events', }) export class EventsGateway implements OnGatewayConnection { @WebSocketServer() server: Server;

handleConnection(client: Socket) { console.log('Client connected:', client.id); }

@SubscribeMessage('message') handleMessage(client: Socket, payload: any): string { return 'Hello world!'; } }

// Add to module @Module({ providers: [EventsGateway], }) export class EventsModule {}

// Configure adapter in main.ts if needed import { IoAdapter } from '@nestjs/platform-socket.io'; app.useWebSocketAdapter(new IoAdapter(app));

Debugging Tools

  1. NestJS Debug Mode

Start with debug flag

nest start --debug --watch

Or add to package.json

"start:debug": "nest start --debug --watch"

  1. VS Code Debugger Configuration

Create .vscode/launch.json :

{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Debug NestJS", "runtimeExecutable": "npm", "runtimeArgs": ["run", "start:debug"], "console": "integratedTerminal", "restart": true, "autoAttachChildProcesses": true, "sourceMaps": true, "envFile": "${workspaceFolder}/.env" }, { "type": "node", "request": "attach", "name": "Attach to NestJS", "port": 9229, "restart": true, "sourceMaps": true } ] }

  1. Docker Debug Configuration

docker-compose.debug.yml

version: '3.8' services: api: command: npm run start:debug ports: - "3000:3000" - "9229:9229" # Debug port environment: - NODE_OPTIONS=--inspect=0.0.0.0:9229

  1. Built-in Logger Service

import { Logger, Injectable } from '@nestjs/common';

@Injectable() export class MyService { private readonly logger = new Logger(MyService.name);

async doSomething() { this.logger.log('Processing started'); this.logger.debug('Debug info', { data: someData }); this.logger.warn('Warning message'); this.logger.error('Error occurred', error.stack); this.logger.verbose('Verbose details'); } }

// Configure logger level in main.ts const app = await NestFactory.create(AppModule, { logger: ['error', 'warn', 'log', 'debug', 'verbose'], });

  1. @nestjs/testing Utilities

import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import * as request from 'supertest';

describe('UsersController (e2e)', () => { let app: INestApplication;

beforeEach(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }) .overrideProvider(UsersService) .useValue(mockUsersService) .compile();

app = moduleFixture.createNestApplication();
await app.init();

});

it('/users (GET)', () => { return request(app.getHttpServer()) .get('/users') .expect(200) .expect({ data: [] }); }); });

The Four Phases (NestJS-specific)

Phase 1: Gather Context

Before debugging, collect all relevant information:

Check NestJS and dependency versions

npm list @nestjs/core @nestjs/common @nestjs/platform-express

Check for peer dependency issues

npm ls 2>&1 | grep -i "peer dep"

Review recent changes

git diff HEAD~5 --name-only | grep -E '.(ts|json)$'

Check environment configuration

cat .env | grep -v -E '^#|^$'

Key Questions:

  • When did the error start occurring?

  • What changes were made recently?

  • Is this reproducible in all environments?

  • Are there any relevant logs or stack traces?

Phase 2: Isolate the Problem

Narrow down the issue systematically:

// 1. Check module structure import { Logger } from '@nestjs/common';

@Module({ imports: [ // Comment out imports one by one to isolate ConfigModule.forRoot(), // DatabaseModule, // Try disabling // UsersModule, // Try disabling ], }) export class AppModule { constructor() { Logger.log('AppModule initialized'); } }

// 2. Add lifecycle logging @Injectable() export class MyService implements OnModuleInit, OnModuleDestroy { private readonly logger = new Logger(MyService.name);

onModuleInit() { this.logger.log('MyService initialized'); }

onModuleDestroy() { this.logger.log('MyService destroyed'); } }

// 3. Test dependency injection manually @Controller() export class TestController { constructor( @Optional() private myService?: MyService, ) { console.log('MyService injected:', !!this.myService); } }

Phase 3: Debug and Fix

Apply targeted debugging techniques:

// 1. For DI issues - check the module graph import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module';

async function bootstrap() { const app = await NestFactory.create(AppModule, { logger: ['verbose'], // Enable all logging });

// Log all registered routes const server = app.getHttpServer(); const router = server._events.request._router; console.log('Registered routes:', router.stack .filter(r => r.route) .map(r => ${Object.keys(r.route.methods)} ${r.route.path}));

await app.listen(3000); }

// 2. For async configuration issues @Module({ imports: [ ConfigModule.forRootAsync({ useFactory: async () => { console.log('ConfigModule factory called'); const config = await loadConfig(); console.log('Config loaded:', config); return config; }, }), ], }) export class AppModule {}

// 3. For guard/interceptor debugging @Injectable() export class DebugGuard implements CanActivate { private readonly logger = new Logger(DebugGuard.name);

canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); this.logger.debug(Guard checking: ${request.method} ${request.url}); this.logger.debug(Headers: ${JSON.stringify(request.headers)}); this.logger.debug(User: ${JSON.stringify(request.user)}); return true; // Allow through for debugging } }

Phase 4: Verify and Document

Ensure the fix is complete and documented:

// 1. Write a test for the fixed issue describe('UserService', () => { it('should resolve dependencies correctly', async () => { const module = await Test.createTestingModule({ imports: [UsersModule], }).compile();

const service = module.get&#x3C;UsersService>(UsersService);
expect(service).toBeDefined();
expect(service.userRepository).toBeDefined();

}); });

// 2. Add error handling to prevent recurrence @Injectable() export class RobustService { private readonly logger = new Logger(RobustService.name);

async riskyOperation() { try { return await this.externalCall(); } catch (error) { this.logger.error(Operation failed: ${error.message}, error.stack); throw new InternalServerErrorException('Operation failed'); } } }

// 3. Document in comments /**

  • UserService handles user-related operations.
  • IMPORTANT: This service depends on DatabaseModule being imported
  • before UsersModule in AppModule to avoid circular dependency issues.
  • @see https://docs.nestjs.com/fundamentals/circular-dependency */ @Injectable() export class UsersService {}

Quick Reference Commands

Debugging Commands

Start in debug mode

npm run start:debug

Start with increased heap memory

NODE_OPTIONS="--max-old-space-size=4096" npm run start:debug

Run with verbose logging

LOG_LEVEL=verbose npm run start

Debug specific module loading

DEBUG=nest:* npm run start

Check TypeScript compilation

npx tsc --noEmit

Validate module structure

npx nest info

Common Fixes

Clear node_modules and reinstall

rm -rf node_modules package-lock.json npm install

Rebuild NestJS

npm run build rm -rf dist && npm run build

Clear cache

npm cache clean --force

Check for duplicate packages

npm dedupe

Update NestJS packages

npx npm-check-updates -u "@nestjs/*" npm install

Inspection Commands

List all modules and providers

npx nest info

Check circular dependencies

npx madge --circular --extensions ts src/

Analyze bundle size

npx source-map-explorer dist/main.js

Check TypeScript config

npx tsc --showConfig

Verify imports

npx ts-unused-exports tsconfig.json

Docker Debugging

Access container shell

docker exec -it <container_id> sh

View container logs

docker logs -f <container_id>

Check container environment

docker exec <container_id> env

Debug with docker compose

docker compose -f docker-compose.debug.yml up

Attach to running container

docker attach <container_id>

Exception Filters for Better Error Handling

import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus, Logger, } from '@nestjs/common';

@Catch() export class AllExceptionsFilter implements ExceptionFilter { private readonly logger = new Logger(AllExceptionsFilter.name);

catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); const request = ctx.getRequest();

const status =
  exception instanceof HttpException
    ? exception.getStatus()
    : HttpStatus.INTERNAL_SERVER_ERROR;

const message =
  exception instanceof HttpException
    ? exception.getResponse()
    : 'Internal server error';

const errorResponse = {
  statusCode: status,
  timestamp: new Date().toISOString(),
  path: request.url,
  method: request.method,
  message: typeof message === 'string' ? message : (message as any).message,
};

this.logger.error(
  `${request.method} ${request.url} ${status}`,
  exception instanceof Error ? exception.stack : String(exception),
);

response.status(status).json(errorResponse);

} }

// Register globally app.useGlobalFilters(new AllExceptionsFilter());

Performance Debugging

// 1. Add timing interceptor @Injectable() export class TimingInterceptor implements NestInterceptor { private readonly logger = new Logger(TimingInterceptor.name);

intercept(context: ExecutionContext, next: CallHandler): Observable<any> { const now = Date.now(); const request = context.switchToHttp().getRequest();

return next.handle().pipe(
  tap(() => {
    const elapsed = Date.now() - now;
    this.logger.log(`${request.method} ${request.url} - ${elapsed}ms`);

    if (elapsed > 1000) {
      this.logger.warn(`Slow request: ${request.url} took ${elapsed}ms`);
    }
  }),
);

} }

// 2. Profile database queries import { Logger } from '@nestjs/common';

// In TypeORM configuration { logging: ['query', 'error', 'warn'], logger: 'advanced-console', maxQueryExecutionTime: 1000, // Log slow queries }

Sources

  • NestJS Official Documentation - Common Errors

  • NestJS Official Documentation - Exception Filters

  • NestJS Official Documentation - Logger

  • Debugging NestJS in VSCode - Plain English

  • Debugging NestJS Applications in VS Code - Medium

  • Step-debugging Docker Compose NestJS services - Rob Allen

  • NestJS Error Handling Patterns - Better Stack

  • Error Handling in NestJS Best Practices - DEV Community

  • 10 Common Mistakes to Avoid in NestJS - Medium

  • Debugging Nest.js Applications - Rookout

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

refactor:flutter

No summary provided by upstream source.

Repository SourceNeeds Review
General

refactor:nestjs

No summary provided by upstream source.

Repository SourceNeeds Review
General

debug:flutter

No summary provided by upstream source.

Repository SourceNeeds Review