diff --git a/src/core/components/request.ts b/src/core/components/request.ts index 8d7ef34cd..17c8d577c 100644 --- a/src/core/components/request.ts +++ b/src/core/components/request.ts @@ -123,7 +123,11 @@ export abstract class AbstractRequest 0 + ) { + // Handle DataSync-style structured error responses: + // { errors: [{ errorCode: "SYN-0008", message: "...", path: "/id" }] } + errorData = errorResponse; + + const errors = errorResponse.errors as Array<{ + errorCode?: string; + message?: string; + path?: string; + }>; + + message = errors + .map((e) => { + const parts: string[] = []; + if (e.errorCode) parts.push(e.errorCode); + if (e.message) parts.push(e.message); + return parts.join(': '); + }) + .join('; '); } else errorData = errorResponse; if ('error' in errorResponse && errorResponse.error instanceof Error) errorData = errorResponse.error; @@ -229,6 +252,35 @@ export class PubNubAPIError extends Error { }; } + /** + * Format a user-facing error message for this API error. + * + * When the error contains structured details extracted from the service response + * (e.g., DataSync `errors` array), those details are included in the message. + * Otherwise, falls back to a generic description. + * + * @param operation - Request operation during which error happened. + * + * @returns Formatted error message string. + */ + public toFormattedMessage(operation: RequestOperation): string { + const fallback = 'REST API request processing error, check status for details'; + + // When errorData contains a structured `errors` array, `this.message` was already + // constructed from it in `createFromServiceResponse` — prefer it over the generic fallback. + if ( + this.errorData && + typeof this.errorData === 'object' && + !('name' in this.errorData && 'message' in this.errorData && 'stack' in this.errorData) && + 'errors' in this.errorData && + Array.isArray((this.errorData as Record).errors) + ) { + return `${operation}: ${this.message}`; + } + + return fallback; + } + /** * Convert API error object to PubNub client error object. *