diff --git a/.changeset/fix-http-request-error-body.md b/.changeset/fix-http-request-error-body.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/http-client/src/http-client.ts b/packages/http-client/src/http-client.ts index 5b7f9ac78b..b89f481425 100644 --- a/packages/http-client/src/http-client.ts +++ b/packages/http-client/src/http-client.ts @@ -1,5 +1,23 @@ import * as http from 'http'; import * as https from 'https'; + +// +import { HttpRequestError } from './http-request-error'; + +// FIND the catch block (looks roughly like this) and change it: +// BEFORE: +} catch (e) { + throw e; +} + +// AFTER: +} catch (e) { + if (isAxiosError(e) && e.response) { + throw new HttpRequestError(e); + } + throw e; +} + import { buildHeadersForDestination, getAgentConfig, diff --git a/packages/http-client/src/http-request-error.spec.ts b/packages/http-client/src/http-request-error.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/http-client/src/http-request-error.ts b/packages/http-client/src/http-request-error.ts new file mode 100644 index 0000000000..e6d27eeb98 --- /dev/null +++ b/packages/http-client/src/http-request-error.ts @@ -0,0 +1,37 @@ +import { AxiosError } from 'axios'; + +/** + * Typed error thrown by executeHttpRequest when the server + * returns a non-2xx response. Surfaces the response body so + * callers can inspect SAP OData/REST error payloads. + */ +export class HttpRequestError extends Error { + readonly statusCode: number | undefined; + readonly responseBody: unknown; + readonly cause: AxiosError; + + constructor(axiosError: AxiosError) { + const status = axiosError.response?.status; + const body = axiosError.response?.data; + const sapMessage = extractSapErrorMessage(body); + const baseMessage = axiosError.message; + + super( + sapMessage + ? `Request failed with status ${status}: ${sapMessage}` + : `Request failed with status ${status}: ${baseMessage}` + ); + + this.name = 'HttpRequestError'; + this.statusCode = status; + this.responseBody = body; + this.cause = axiosError; + } +} + +function extractSapErrorMessage(body: unknown): string | undefined { + if (!body || typeof body !== 'object') return undefined; + const err = (body as any)?.error; + const msg = err?.message?.value ?? err?.message ?? err?.Message; + return typeof msg === 'string' ? msg : undefined; +} \ No newline at end of file diff --git a/packages/http-client/src/index.ts b/packages/http-client/src/index.ts index e1ad0b1609..3693b35a7a 100644 --- a/packages/http-client/src/index.ts +++ b/packages/http-client/src/index.ts @@ -35,3 +35,4 @@ export type { ParameterEncoder } from './http-client-types'; export { defaultDisallowedKeys } from './http-request-config'; +export { HttpRequestError } from './http-request-error'; \ No newline at end of file