Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code f2428dfa8a chore: improve monitoring for NULL bytes in REST API input cause PostgreSQL reje
### Monitoring Fix: Include PostgreSQL error code in Sentry exception messages

**File:** `http-exception-handler.service.ts`

For `PostgresException` instances that still reach the 500 handler (non-22xxx errors like constraint violations, syntax errors, etc.), the exception message now includes the PostgreSQL error code: `"Data validation error. (PG error code: 42703)"`.

**Before:** Sentry showed only `InternalServerErrorException: Data validation error.` with no way to distinguish between different PostgreSQL error types without reading source code.

**After:** The PG error code is embedded in the Sentry error title, enabling:
- Better Sentry issue grouping by error code
- Faster triage — engineers can immediately identify the error class (23xxx = constraint, 42xxx = syntax/schema, 53xxx = resources)
- Easier correlation with PostgreSQL documentation
2026-03-06 13:06:12 +00:00
Sonarly Claude Code f70340a2f5 NULL bytes in REST API input cause PostgreSQL rejection, misclassified as 500
https://sonarly.com/issue/3840?type=bug

The REST API PATCH endpoint passes unsanitized string data containing \u0000 (NULL byte) characters to PostgreSQL, which rejects them. The error is then misclassified as a 500 Internal Server Error instead of 400 Bad Request.

Fix: ### Root Cause Fix: Classify PostgreSQL data exceptions as client input errors

**File:** `compute-twenty-orm-exception.ts`

Replaced the narrow check for only `INVALID_TEXT_REPRESENTATION` (PostgreSQL code `22P02`) with a broader check for all class-22 (Data Exception) errors using `errorCode.startsWith('22')`.

**Before:** Only `22P02` was classified as `INVALID_INPUT` → 400 Bad Request. All other 22xxx errors (including `22021` CHARACTER_NOT_IN_REPERTOIRE and `22P05` UNTRANSLATABLE_CHARACTER triggered by `\u0000` null bytes) fell through to the catch-all `PostgresException` → 500 Internal Server Error.

**After:** All PostgreSQL class-22 errors are now correctly classified as `TwentyORMException` with `INVALID_INPUT` code. This flows through:
1. `workspaceQueryRunnerRestApiExceptionHandler` → `BadRequestException` (400)
2. `HttpExceptionHandlerService` → returns 400 with the actual PostgreSQL error message

This is correct because [all 22xxx codes](https://www.postgresql.org/docs/current/errcodes-appendix.html) are "Data Exception" errors caused by invalid input data, not server failures. The UNIQUE_VIOLATION (23505) check runs before this, so it's unaffected.
2026-03-06 13:06:12 +00:00
2 changed files with 5 additions and 3 deletions
@@ -105,7 +105,9 @@ export class HttpExceptionHandlerService {
}
if (exception instanceof PostgresException) {
exception = new InternalServerErrorException(exception.message);
exception = new InternalServerErrorException(
`${exception.message} (PG error code: ${exception.code})`,
);
statusCode = 500;
}
@@ -51,9 +51,9 @@ export const computeTwentyORMException = async (
);
}
if (errorCode === POSTGRESQL_ERROR_CODES.INVALID_TEXT_REPRESENTATION) {
if (isDefined(errorCode) && errorCode.startsWith('22')) {
return new TwentyORMException(
error.message, // safe and useful
error.message,
TwentyORMExceptionCode.INVALID_INPUT,
);
}