Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 0300a372a3 fix(rest-api): handle network-level errors in RestApiService catch block
https://sonarly.com/issue/32473?type=bug

When the server cannot reach its own GraphQL endpoint (e.g., ECONNREFUSED due to misconfigured SERVER_URL), the REST API catch block throws a TypeError trying to access `err.response.data.errors` on an undefined response, resulting in an empty 500 response with no logging.

Fix: Fixed the unguarded property access in `RestApiService.call()` catch block that caused a TypeError when the internal GraphQL request fails at the network level (e.g., ECONNREFUSED, ETIMEDOUT).

**Changes:**
1. Added `isAxiosError` guard (from axios, matching team conventions in `http-tool.ts` and `search-help-center-tool.ts`) to safely check whether `err.response?.data?.errors` exists before accessing it
2. When the error is a network-level failure (no response object), the service now throws a proper `InternalServerErrorException` with the original error message instead of crashing with a TypeError
3. Added `Logger` to the service (matching team pattern in `RestApiCoreController`) to log network failures at ERROR level, enabling infrastructure debugging for self-hosted operators

The fix preserves the existing behavior for GraphQL-level errors (HTTP responses with error payloads) while properly handling network failures that produce no HTTP response.
2026-04-29 13:39:27 +00:00
@@ -1,6 +1,10 @@
import { Injectable } from '@nestjs/common';
import {
Injectable,
InternalServerErrorException,
Logger,
} from '@nestjs/common';
import { type AxiosResponse } from 'axios';
import { type AxiosResponse, isAxiosError } from 'axios';
import { type Query } from 'src/engine/api/rest/core/types/query.type';
import { RestApiException } from 'src/engine/api/rest/errors/RestApiException';
@@ -14,6 +18,8 @@ export enum GraphqlApiType {
@Injectable()
export class RestApiService {
private readonly logger = new Logger(RestApiService.name);
constructor(
private readonly secureHttpClientService: SecureHttpClientService,
) {}
@@ -41,7 +47,17 @@ export class RestApiService {
},
});
} catch (err) {
throw new RestApiException(err.response.data.errors);
if (isAxiosError(err) && err.response?.data?.errors) {
throw new RestApiException(err.response.data.errors);
}
this.logger.error(
`Failed to reach internal GraphQL endpoint at ${url}: ${err.message}`,
);
throw new InternalServerErrorException(
`Internal GraphQL request failed: ${err.message}`,
);
}
if (response.data.errors?.length) {