Skip to content

Conversation

ricaelchiquetti
Copy link

@ricaelchiquetti ricaelchiquetti commented Sep 8, 2025

feat: Implement standardized error handling for WhatsApp API responses

Description

This Pull Request introduces a complete refactoring of the WhatsApp API error handling to ensure that error responses are more detailed, consistent, and easier to debug. Previously, many errors from the Meta API were masked by generic messages, making it difficult to identify the root cause of issues.


What was done?

  • Standard Error Formatter Creation: A new utility, createMetaErrorResponse, has been created in src/utils/errorResponse.ts. This function is responsible for taking a raw error from the WhatsApp API and transforming it into a well-structured and consistent JSON response object.
  • Improved Error Propagation: The TemplateService was modified to propagate the complete error object returned by the WhatsApp API, instead of throwing a new error with a generic message. This ensures that no important details (like fbtrace_id, error_subcode, etc.) are lost.
  • Implementation in API Routes: The endpoints in BusinessRouter and TemplateRouter were updated to use try...catch and call the new createMetaErrorResponse function in the catch block. This ensures that all communication with the client follows the new error standard.

Why is this necessary?

  • Debugging Difficulty: It was hard to diagnose WhatsApp integration issues because the error messages were generic and did not contain the full context provided by Meta.
  • Inconsistency: Different parts of the code handled errors in different ways, resulting in an inconsistent experience for developers consuming the API.
  • Loss of Information: Valuable details for support and debugging, such as the fbtrace_id, were being discarded.

How to test?

  1. Run the application.
  2. Make a request to one of the affected endpoints (e.g., POST /template/create) with data that you know will cause an error in the WhatsApp API (for example, an invalid component format or a template name that violates the rules).
  3. Check the API response. It should contain a JSON with the structure defined by the MetaErrorResponse interface, including fields like status, message, and details with specific information from the WhatsApp error.
  4. Confirm that the HTTP response status is 400 Bad Request.

Summary by Sourcery

Implement a consistent error-handling layer for WhatsApp API interactions by adding a formatting utility, updating service error propagation, and standardizing router error responses

Enhancements:

  • Introduce createMetaErrorResponse utility to format and standardize WhatsApp API errors
  • Wrap BusinessRouter and TemplateRouter endpoints in try/catch, log failures, and return standardized MetaErrorResponse
  • Refactor TemplateService to propagate raw Meta API errors with full context and return complete error data from axios calls

Copy link
Contributor

sourcery-ai bot commented Sep 8, 2025

Reviewer's Guide

Refactored WhatsApp API error handling by introducing a centralized formatter utility, enhancing service error propagation, and standardizing error responses in API routes.

Sequence diagram for API error handling in BusinessRouter and TemplateRouter

sequenceDiagram
  participant Client
  participant Router
  participant Service
  participant WhatsAppAPI
  participant ErrorUtil

  Client->>Router: POST /template/create (invalid data)
  Router->>Service: dataValidate & createTemplate
  Service->>WhatsAppAPI: requestTemplate
  WhatsAppAPI-->>Service: Error response
  Service-->>Router: Throws error with WhatsApp error details
  Router->>ErrorUtil: createMetaErrorResponse(error, context)
  ErrorUtil-->>Router: Standardized error response
  Router-->>Client: HTTP 400 with MetaErrorResponse
Loading

Class diagram for standardized error handling utility and response structure

classDiagram
  class MetaErrorResponse {
    +number status
    +string error
    +string message
    +details: object
    +string timestamp
  }
  class details {
    +string whatsapp_error
    +string|number whatsapp_code
    +string error_user_title
    +string error_user_msg
    +string error_type
    +number|null error_subcode
    +string|null fbtrace_id
    +string context
    +string type
  }
  MetaErrorResponse --> details
  class createMetaErrorResponse {
    +MetaErrorResponse createMetaErrorResponse(error, context)
  }
  createMetaErrorResponse ..> MetaErrorResponse : returns
Loading

File-Level Changes

Change Details Files
Created a standardized MetaErrorResponse formatter
  • Defined MetaErrorResponse interface with detailed error fields and timestamp
  • Implemented createMetaErrorResponse to map raw WhatsApp errors into the standard format
src/utils/errorResponse.ts
Standardized error handling in BusinessRouter and TemplateRouter
  • Wrapped each route handler in try/catch blocks
  • Logged original errors for debugging
  • Returned formatted error responses using createMetaErrorResponse
src/api/routes/business.router.ts
src/api/routes/template.router.ts
Improved error propagation in TemplateService
  • Threw original WhatsApp API error with full metadata instead of generic messages
  • Logged detailed errors before rethrowing
  • Returned complete API error payload or threw connection errors in requestTemplate
src/api/services/template.service.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Replace all console.error calls in your catch blocks with the project’s centralized logger so that error logs remain consistent and include structured metadata like request IDs.
  • Right now createMetaErrorResponse always returns HTTP 400; consider deriving the status code from the WhatsApp error code or allowing callers to override it for cases like authentication (401) or rate-limit (429) errors.
  • In TemplateService, instead of rethrowing a raw Error, wrap the original error and its metadata in a custom Error subclass to preserve stack trace and ensure your error contract remains clear.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Replace all console.error calls in your catch blocks with the project’s centralized logger so that error logs remain consistent and include structured metadata like request IDs.
- Right now createMetaErrorResponse always returns HTTP 400; consider deriving the status code from the WhatsApp error code or allowing callers to override it for cases like authentication (401) or rate-limit (429) errors.
- In TemplateService, instead of rethrowing a raw Error, wrap the original error and its metadata in a custom Error subclass to preserve stack trace and ensure your error contract remains clear.

## Individual Comments

### Comment 1
<location> `src/utils/errorResponse.ts:24` </location>
<code_context>
+/**
+ * Creates standardized error response for Meta/WhatsApp API errors
+ */
+export function createMetaErrorResponse(error: any, context: string): MetaErrorResponse {
+  // Extract Meta/WhatsApp specific error fields
+  const metaError = error.template || error;
</code_context>

<issue_to_address>
The error response always uses BAD_REQUEST status, which may not fit all error scenarios.

Allow the status code to be set dynamically based on the error type, so responses can accurately reflect server or authorization errors.

Suggested implementation:

```typescript
/**
 * Creates standardized error response for Meta/WhatsApp API errors
 * @param error - The error object from Meta/WhatsApp API
 * @param context - Context string for the error
 * @param status - Optional HTTP status code (defaults to BAD_REQUEST)
 * @param errorString - Optional error string (defaults to 'Bad Request')
 */
export function createMetaErrorResponse(
  error: any,
  context: string,
  status: number = HttpStatus.BAD_REQUEST,
  errorString: string = 'Bad Request'
): MetaErrorResponse {
  // Extract Meta/WhatsApp specific error fields
  const metaError = error.template || error;
  const errorUserTitle = metaError.error_user_title || metaError.message || 'Unknown error';
  const errorUserMsg = metaError.error_user_msg || metaError.message || 'Unknown error';

  return {
    status: status,
    error: errorString,
    message: errorUserTitle,
    details: {
      whatsapp_error: errorUserMsg,
      whatsapp_code: metaError.code || 'UNKNOWN_ERROR',

```

You will need to update all usages of `createMetaErrorResponse` to optionally pass the `status` and `errorString` parameters where appropriate, e.g.:
```ts
createMetaErrorResponse(error, context, HttpStatus.UNAUTHORIZED, 'Unauthorized')
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

/**
* Creates standardized error response for Meta/WhatsApp API errors
*/
export function createMetaErrorResponse(error: any, context: string): MetaErrorResponse {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: The error response always uses BAD_REQUEST status, which may not fit all error scenarios.

Allow the status code to be set dynamically based on the error type, so responses can accurately reflect server or authorization errors.

Suggested implementation:

/**
 * Creates standardized error response for Meta/WhatsApp API errors
 * @param error - The error object from Meta/WhatsApp API
 * @param context - Context string for the error
 * @param status - Optional HTTP status code (defaults to BAD_REQUEST)
 * @param errorString - Optional error string (defaults to 'Bad Request')
 */
export function createMetaErrorResponse(
  error: any,
  context: string,
  status: number = HttpStatus.BAD_REQUEST,
  errorString: string = 'Bad Request'
): MetaErrorResponse {
  // Extract Meta/WhatsApp specific error fields
  const metaError = error.template || error;
  const errorUserTitle = metaError.error_user_title || metaError.message || 'Unknown error';
  const errorUserMsg = metaError.error_user_msg || metaError.message || 'Unknown error';

  return {
    status: status,
    error: errorString,
    message: errorUserTitle,
    details: {
      whatsapp_error: errorUserMsg,
      whatsapp_code: metaError.code || 'UNKNOWN_ERROR',

You will need to update all usages of createMetaErrorResponse to optionally pass the status and errorString parameters where appropriate, e.g.:

createMetaErrorResponse(error, context, HttpStatus.UNAUTHORIZED, 'Unauthorized')

@DavidsonGomes
Copy link
Collaborator

Please fix the lint with npm run lint

@ricaelchiquetti
Copy link
Author

Please fix the lint with npm run lint

the build is still failing for a different reason. The current errors are from the TypeScript compiler, not from the linter. Looking at the logs, it seems they are caused by breaking changes in a recent update of the Baileys library.

@DavidsonGomes DavidsonGomes merged commit 8276046 into EvolutionAPI:develop Sep 17, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants