fix(server): handle network errors in RestApiService catch block (#20644)

## Summary
- Added safe null check for `err.response?.data?.errors` in
`RestApiService.call()` catch block
- When the internal HTTP client fails with a network-level error
(ECONNREFUSED, timeout), `err.response` is `undefined` — accessing
`.data.errors` on it throws a `TypeError` which gets silently swallowed,
returning an empty 500
- Now falls back to throwing the raw error message for network failures
instead of crashing

## Changes
- `packages/twenty-server/src/engine/api/rest/rest-api.service.ts`

Fixes #20136

---------

Co-authored-by: Marie Stoppa <marie@twenty.com>
This commit is contained in:
Shubham Singh
2026-05-18 15:21:42 +05:30
committed by GitHub
parent 45ac3e8218
commit 01535a3b3e
2 changed files with 8 additions and 3 deletions
@@ -6,6 +6,7 @@ import { type Query } from 'src/engine/api/rest/core/types/query.type';
import { RestApiException } from 'src/engine/api/rest/errors/RestApiException';
import { type RequestContext } from 'src/engine/api/rest/types/RequestContext';
import { SecureHttpClientService } from 'src/engine/core-modules/secure-http-client/secure-http-client.service';
import { isDefined } from 'twenty-shared/utils';
export enum GraphqlApiType {
CORE = 'core',
@@ -41,10 +42,14 @@ export class RestApiService {
},
});
} catch (err) {
throw new RestApiException(err.response.data.errors);
if (isDefined(err.response?.data?.errors)) {
throw new RestApiException(err.response.data.errors);
}
throw err;
}
if (response.data.errors?.length) {
if (isDefined(response.data.errors) && response.data.errors.length > 0) {
throw new RestApiException(response.data.errors);
}
@@ -35,6 +35,6 @@ export class UnhandledExceptionFilter implements ExceptionFilter {
const status =
exception instanceof HttpException ? exception.getStatus() : 500;
response.status(status).json(exception.response);
response.status(status).json(exception.response ?? exception.message);
}
}