Qadam Roadmap
проектdocs/Agents/rules/quality-error-handling.md

quality-error-handling.md

Обновлён 1 апр. 2026 г., 12:41 · 0 комментариев


title: Error Handling Patterns impact: HIGH impactDescription: Proper error handling ensures debuggable and secure code tags: errors, nestjs, services, exceptions

Паспорт документа

  • Статус документа: living standard
  • Актуально на: 28 марта 2026 года
  • Владелец: backend/platform-команда
  • Пересмотр: при изменении инженерной практики, CI/CD, архитектурных правил или локального workflow
  • Область применения: внутренние rule/reference-card документы для инженерной команды
  • Связанные документы:

Error Handling Patterns

Impact: HIGH

Descriptive Errors

Always include context in error messages — IDs, slugs, seller references — so logs are actionable.

Error Classes by Layer

Use the right exception class depending on where you are in the code.

In Controllers (HTTP layer) — NestJS exceptions

import { NotFoundException, BadRequestException, ForbiddenException } from '@nestjs/common';

@Get(':slug')
async getBySlug(@Param('slug') slug: string) {
  const item = await this.itemService.findBySlug(slug);
  if (!item) throw new NotFoundException(`Item with slug "${slug}" not found`);
  return item;
}

In Services (business logic) — Domain exceptions

import { DomainException, ErrorCode } from '@repo/shared';

@Injectable()
export class ItemService {
  async publish(itemId: string, sellerId: string) {
    const item = await this.itemRepo.findById(itemId);
    if (!item) {
      throw new DomainException(ErrorCode.ITEM_NOT_FOUND, `Item ${itemId} not found`);
    }
    if (item.sellerId !== sellerId) {
      throw new DomainException(ErrorCode.FORBIDDEN, `Seller ${sellerId} does not own item ${itemId}`);
    }
  }
}

Global Exception Filter

NestJS global exception filter converts DomainException to proper HTTP responses automatically. Services don't need to know about HTTP status codes.

// common/filters/domain-exception.filter.ts
@Catch(DomainException)
export class DomainExceptionFilter implements ExceptionFilter {
  catch(exception: DomainException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const status = this.mapErrorCodeToStatus(exception.code);

    response.status(status).send({
      statusCode: status,
      errorCode: exception.code,
      message: exception.message,
    });
  }
}

Rules

  • Controllers: Use @nestjs/common exceptions (NotFoundException, BadRequestException, etc.)
  • Services: Use DomainException with ErrorCode enum from @repo/shared
  • Repositories: Let Prisma errors bubble up — the service handles them
  • Never: Use plain throw new Error() in services — always use typed exceptions