> ## Documentation Index
> Fetch the complete documentation index at: https://ihub.learnille.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Backend error handling

> Shared HTTP error contract, exception mapping, and regression checks

**Owner:** Backend Engineering

**Last reviewed:** 2026-09-27

**Next review:** 2026-12-27

## Request flow

Route validation and services throw exceptions. `ExceptionsModule.forRoot()`
registers the single global `AppExceptionsFilter`, which delegates serialization
to `AllExceptionsFilter`. Feature modules register `AppException` mappings through
`ExceptionsModule.forFeature()`. Do not register another catch-all filter in
`main.ts`: doing so previously bypassed those mappings.

All HTTP failures have `statusCode`, a readable string `message`, `data` (details
or null), and `error`. DTO validation returns 400, `errorCode: 10000`, and the
individual messages in `data` and `reasons`. Native Nest message arrays become a
joined summary plus a `data` array. Zod errors retain their field/message/code
objects in `errors` and `data`. Expired-token responses retain status 498,
application code 10198 and optional `expiredAt`. Cooldown and account-linking
metadata is preserved.

The public integration guide is in the docs repository at
`api-reference/errors.mdx`. Frontends can display `message` directly. Clients
that turn responses into plain `Error` objects must retain structured response
data separately if they need field errors or cooldown UI.

## Writing service errors

* Use `BadRequestException` for invalid requests, `ForbiddenException` for denied
  access and `NotFoundException` for missing resources. Do not throw a generic
  `Error` for expected user-facing failures.
* Preserve typed exceptions through catch blocks. Do not convert every failure
  to 400 or 500, or infer status from words in an error message.
* Register custom `AppException` mappings in the owning module. An unmapped
  application exception remains an internal failure.
* Keep unexpected infrastructure failures as server errors. Do not expose raw
  provider errors, SQL, credentials or stacks in an `HttpException` response.
  The filter logs unexpected failures and sends a generic message.
* Validators must handle missing and incorrectly typed input without throwing.
  The password validator now checks the type before reading its length.

The audit corrected error classification in room/notification access, file
linking, review deletion, search limits, category product types, queue lookup and
webhook recovery. Analytics and session-room catches preserve existing HTTP
errors. Student interest-group and search-index failures no longer masquerade as
invalid input. Payment processing and webhook acknowledgement semantics were not
changed.

## Verification

From `server`, run:

```sh theme={null}
pnpm exec vitest run --config test/vitest.unit.config.ts src/common/filters/all-exception.filter.spec.ts src/common/filters/domain-errors.spec.ts src/exceptions/error-response.http.spec.ts
pnpm typecheck:ci
```

The HTTP suite binds a temporary loopback port and uses the actual global filter
registration. Unit tests cover password values of different types, valid input,
Zod errors, exception mappings, token/cooldown metadata, safe internal errors and
domain errors without unintended writes.

Manual checks on the configured test environment:

1. Submit a weak, missing and mismatched password to registration, reset-password
   and change-password routes. Expect 400 and a readable message in the frontend.
2. Submit valid data to confirm successful behavior is unchanged.
3. Exercise invalid authentication, expired tokens, forbidden operations,
   missing resources, cooldowns and rate limits; verify status and metadata.
4. Trigger a controlled upstream outage in a test environment. Expect a server
   error without internal details, and a useful server log.

During this audit, the broader selected regression suites had 47 failures that
also reproduced against the unchanged HEAD: 16 auth mock failures and 31 missing
provider/mock failures across InstantDB, OpenSearch and reviews. Those legacy
suite fixtures need separate repair; they are not evidence that live flows pass.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.