Common Backend Issues & Solutions

Troubleshooting guide for common backend-api issues encountered during development

Common Backend Issues & Solutions

Quick reference for common backend issues and their solutions.

Issue #1: Modules Not Persisting (MongoDB Upsert Conflict)

Symptoms

Error in Backend Logs

❌ Failed to upsert module [ModuleName]: Updating the path 'createdAt' would create a conflict at 'createdAt'

Root Cause

The upsertMany method was including createdAt in both $set and $setOnInsert operators, which MongoDB doesn't allow.

Solution

Separate the fields - createdAt should ONLY be in $setOnInsert:

// ❌ WRONG
const module = { ...fields, createdAt: now };
await collection.updateOne(
  { _id },
  { $set: module, $setOnInsert: { createdAt: now } },
  { upsert: true }
);

// ✅ CORRECT  
const updateDoc = { ...fields, updatedAt: now }; // No createdAt!
await collection.updateOne(
  { _id },
  { $set: updateDoc, $setOnInsert: { createdAt: now } },
  { upsert: true }
);

File Fixed

apis/backend-api/src/app/spaces/space-modules.service.ts - upsertMany() method

Date Fixed

December 1, 2025


Issue #2: Request Body Empty (ValidationPipe Stripping Properties)

Symptoms

Root Cause

Global ValidationPipe configured with whitelist: true strips properties that aren't decorated in DTOs. Since we use TypeScript interfaces (not classes with decorators), ALL properties get stripped.

Solution

Configure ValidationPipe to NOT strip properties:

// main.ts
app.useGlobalPipes(
  new ValidationPipe({
    whitelist: false,            // DON'T strip unknown properties
    forbidNonWhitelisted: false, // DON'T throw on unknown properties
    transform: true,
    transformOptions: {
      enableImplicitConversion: true
    }
  })
);

File Fixed

apis/backend-api/src/main.ts


Issue #3: Controller Not Loading

Symptoms

Debugging Steps

  1. Check controller is registered in module:

    @Module({
      controllers: [SpacesController, SpaceModulesController], // Both listed?
    })
    
  2. Check for circular dependencies:

    // Use forwardRef for circular imports
    imports: [forwardRef(() => BackendAuthModule)]
    
  3. Add health check endpoint for testing:

    @Get('health')
    healthCheck() {
      return { status: 'ok', controller: 'SpaceModulesController' };
    }
    
  4. Check route conflicts:

    • More specific routes should come BEFORE generic ones
    • /batch should be before /:id

Issue #4: EADDRINUSE Port Already in Use

Symptoms

Error: listen EADDRINUSE: address already in use 0.0.0.0:3000

Solution

Kill processes using the port:

# Find and kill process
lsof -ti:3000 | xargs kill -9

# Or kill all node processes
pkill -9 node

# Then restart
yarn serve:backend-only

Issue #5: Auth Guard Blocking Requests

Symptoms

Debugging Steps

  1. Check guard is applied correctly:

    @UseGuards(BackendAuthGuard)  // Class level OR method level, not both
    
  2. Test without auth (temporarily):

    @Get('test')
    // No @UseGuards - for testing only!
    test() { return { ok: true }; }
    
  3. Verify JWT token format:

    curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3000/api/endpoint
    

🔍 General Debugging Tips

1. Add Extensive Logging

this.logger.log(`📦 Method called with:`, { param1, param2 });
console.log('RAW BODY:', JSON.stringify(body, null, 2));

2. Test with curl

# GET request
curl http://localhost:3000/api/spaces/SPACE_ID/modules/health

# POST request with body
curl -X POST http://localhost:3000/api/endpoint \
  -H "Content-Type: application/json" \
  -d '{"key":"value"}'

3. Check Backend Terminal

The terminal shows all NestJS logs including errors that might not be returned to the client.

4. Verify Rebuild

After code changes, ensure the backend has rebuilt:


📋 Quick Checklist for New Endpoints