> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/EvolutionAPI/evolution-api/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Understand error codes, response formats, and troubleshooting guidance for Evolution API

Evolution API uses standard HTTP status codes and consistent error response formats to communicate issues. Understanding these error patterns will help you build robust integrations.

## HTTP Status Codes

Evolution API implements the following HTTP status codes (`src/api/routes/index.router.ts:28-36`):

| Status Code | Name                    | Description                                       |
| ----------- | ----------------------- | ------------------------------------------------- |
| `200`       | OK                      | Request succeeded                                 |
| `201`       | CREATED                 | Resource created successfully                     |
| `400`       | BAD\_REQUEST            | Invalid request parameters or body                |
| `401`       | UNAUTHORIZED            | Missing or invalid authentication                 |
| `403`       | FORBIDDEN               | Valid authentication but insufficient permissions |
| `404`       | NOT\_FOUND              | Requested resource does not exist                 |
| `500`       | INTERNAL\_SERVER\_ERROR | Server encountered an unexpected error            |

<Note>
  All error responses include a consistent JSON structure for easy parsing and error handling.
</Note>

## Error Response Format

Evolution API error responses follow this standard format:

```json theme={null}
{
  "status": 400,
  "error": "Bad Request",
  "message": "Descriptive error message or array of errors"
}
```

<ParamField path="status" type="number" required>
  The HTTP status code (400, 401, 403, 404, or 500)
</ParamField>

<ParamField path="error" type="string" required>
  A human-readable error name matching the HTTP status
</ParamField>

<ParamField path="message" type="string | array" required>
  Detailed error description. Can be a string or array of error messages
</ParamField>

## Error Types and Exceptions

Evolution API defines custom exception classes in `src/exceptions/`:

### 400 Bad Request

**Implementation**: `src/exceptions/400.exception.ts`

Thrown when the request contains invalid parameters, missing required fields, or fails validation.

<CodeGroup>
  ```json Example Response theme={null}
  {
    "status": 400,
    "error": "Bad Request",
    "message": [
      "number is required",
      "text must be a string"
    ]
  }
  ```

  ```typescript Exception Class theme={null}
  export class BadRequestException {
    constructor(...objectError: any[]) {
      throw {
        status: HttpStatus.BAD_REQUEST,
        error: 'Bad Request',
        message: objectError.length > 0 ? objectError : undefined,
      };
    }
  }
  ```
</CodeGroup>

**Common Causes:**

* Missing required fields in request body
* Invalid data types (string instead of number)
* JSONSchema validation failures
* Malformed JSON in request body
* Invalid phone number formats
* File upload errors

**Example Scenarios:**

<Accordion title="Missing Required Field">
  **Request:**

  ```bash theme={null}
  POST /message/sendText/my-instance
  apikey: valid-token

  {
    "text": "Hello"
    # Missing "number" field
  }
  ```

  **Response (400):**

  ```json theme={null}
  {
    "status": 400,
    "error": "Bad Request",
    "message": ["requires property \"number\""]
  }
  ```
</Accordion>

<Accordion title="Invalid Data Type">
  **Request:**

  ```bash theme={null}
  POST /message/sendText/my-instance
  apikey: valid-token

  {
    "number": 5511999999999,  // Should be string
    "text": "Hello"
  }
  ```

  **Response (400):**

  ```json theme={null}
  {
    "status": 400,
    "error": "Bad Request",
    "message": ["number is not of a type(s) string"]
  }
  ```
</Accordion>

<Accordion title="Group JID Format Error">
  **Request:**

  ```bash theme={null}
  POST /group/updateGroupPicture/my-instance?groupJid=invalid-format
  apikey: valid-token

  { "image": "https://..." }
  ```

  **Response (400):**

  ```json theme={null}
  {
    "status": 400,
    "error": "Bad Request",
    "message": "The group id needs to be informed in the query"
  }
  ```

  The validation logic is in `src/api/abstract/abstract.router.ts:96-144`.
</Accordion>

### 401 Unauthorized

**Implementation**: `src/exceptions/401.exception.ts`

Thrown when authentication is missing or invalid.

<CodeGroup>
  ```json Example Response theme={null}
  {
    "status": 401,
    "error": "Unauthorized",
    "message": "Unauthorized"
  }
  ```

  ```typescript Exception Class theme={null}
  export class UnauthorizedException {
    constructor(...objectError: any[]) {
      throw {
        status: HttpStatus.UNAUTHORIZED,
        error: 'Unauthorized',
        message: objectError.length > 0 ? objectError : 'Unauthorized',
      };
    }
  }
  ```
</CodeGroup>

**Common Causes:**

* Missing `apikey` header
* Invalid global API key
* Invalid instance token
* Using instance token for another instance
* Expired or revoked credentials

**Example Scenarios:**

<Accordion title="Missing API Key Header">
  **Request:**

  ```bash theme={null}
  GET /instance/connectionState/my-instance
  # Missing apikey header
  ```

  **Response (401):**

  ```json theme={null}
  {
    "status": 401,
    "error": "Unauthorized",
    "message": "Unauthorized"
  }
  ```

  Validated in `src/api/guards/auth.guard.ts:15-17`.
</Accordion>

<Accordion title="Invalid API Key">
  **Request:**

  ```bash theme={null}
  GET /instance/connectionState/my-instance
  apikey: wrong-key-12345
  ```

  **Response (401):**

  ```json theme={null}
  {
    "status": 401,
    "error": "Unauthorized",
    "message": "Unauthorized"
  }
  ```

  The key is validated against both the global key and instance tokens in `src/api/guards/auth.guard.ts:19-50`.
</Accordion>

<Accordion title="Wrong Instance Token">
  **Request:**

  ```bash theme={null}
  POST /message/sendText/instance-a
  apikey: token-for-instance-b

  { "number": "123", "text": "test" }
  ```

  **Response (401):**

  ```json theme={null}
  {
    "status": 401,
    "error": "Unauthorized",
    "message": "Unauthorized"
  }
  ```
</Accordion>

### 403 Forbidden

**Implementation**: `src/exceptions/403.exception.ts`

Thrown when authentication is valid but the operation is not permitted.

<CodeGroup>
  ```json Example Response theme={null}
  {
    "status": 403,
    "error": "Forbidden",
    "message": [
      "Missing global api key",
      "The global api key must be set"
    ]
  }
  ```

  ```typescript Exception Class theme={null}
  export class ForbiddenException {
    constructor(...objectError: any[]) {
      throw {
        status: HttpStatus.FORBIDDEN,
        error: 'Forbidden',
        message: objectError.length > 0 ? objectError : undefined,
      };
    }
  }
  ```
</CodeGroup>

**Common Causes:**

* Using instance token to create instances (requires global key)
* Attempting to access protected administrative endpoints
* IP address not in metrics allowlist
* Invalid metrics authentication

**Example Scenarios:**

<Accordion title="Instance Token Used for Creation">
  **Request:**

  ```bash theme={null}
  POST /instance/create
  apikey: some-instance-token

  {
    "instanceName": "new-instance",
    "token": "new-token"
  }
  ```

  **Response (403):**

  ```json theme={null}
  {
    "status": 403,
    "error": "Forbidden",
    "message": [
      "Missing global api key",
      "The global api key must be set"
    ]
  }
  ```

  Instance creation requires the global API key (`src/api/guards/auth.guard.ts:23-25`).
</Accordion>

<Accordion title="Metrics IP Not Allowed">
  **Request:**

  ```bash theme={null}
  GET /metrics
  # From IP 203.0.113.5 (not in allowlist)
  ```

  **Response (403):**

  ```text theme={null}
  Forbidden: IP not allowed
  ```

  IP validation is in `src/api/routes/index.router.ts:48-63`.
</Accordion>

<Accordion title="Asset Path Traversal Blocked">
  **Request:**

  ```bash theme={null}
  GET /assets/../../../etc/passwd
  ```

  **Response (403):**

  ```text theme={null}
  Forbidden
  ```

  Path traversal protection is in `src/api/routes/index.router.ts:169-183`.
</Accordion>

### 404 Not Found

**Implementation**: `src/exceptions/404.exception.ts`

Thrown when the requested resource does not exist.

<CodeGroup>
  ```json Example Response theme={null}
  {
    "status": 404,
    "error": "Not Found",
    "message": "Instance my-instance not found"
  }
  ```

  ```typescript Exception Class theme={null}
  export class NotFoundException {
    constructor(...objectError: any[]) {
      throw {
        status: HttpStatus.NOT_FOUND,
        error: 'Not Found',
        message: objectError.length > 0 ? objectError : undefined,
      };
    }
  }
  ```
</CodeGroup>

**Common Causes:**

* Instance name does not exist
* Chat or message ID not found
* Group JID does not exist
* Contact not in WhatsApp database
* File or media not found

**Example Scenarios:**

<Accordion title="Instance Not Found">
  **Request:**

  ```bash theme={null}
  GET /instance/connectionState/nonexistent-instance
  apikey: valid-global-key
  ```

  **Response (404):**

  ```json theme={null}
  {
    "status": 404,
    "error": "Not Found",
    "message": "Instance nonexistent-instance not found"
  }
  ```
</Accordion>

<Accordion title="Chat Not Found">
  **Request:**

  ```bash theme={null}
  GET /chat/findMessages/my-instance?id=nonexistent@s.whatsapp.net
  apikey: valid-token
  ```

  **Response (404):**

  ```json theme={null}
  {
    "status": 404,
    "error": "Not Found",
    "message": "Chat not found"
  }
  ```
</Accordion>

<Accordion title="Media File Not Found">
  **Request:**

  ```bash theme={null}
  GET /assets/nonexistent-file.png
  ```

  **Response (404):**

  ```text theme={null}
  File not found
  ```

  File existence check is in `src/api/routes/index.router.ts:185-190`.
</Accordion>

### 500 Internal Server Error

**Implementation**: `src/exceptions/500.exception.ts`

Thrown when the server encounters an unexpected error.

<CodeGroup>
  ```json Example Response theme={null}
  {
    "status": 500,
    "error": "Internal Server Error",
    "message": "An unexpected error occurred while processing your request"
  }
  ```

  ```typescript Exception Class theme={null}
  export class InternalServerErrorException {
    constructor(...objectError: any[]) {
      throw {
        status: HttpStatus.INTERNAL_SERVER_ERROR,
        error: 'Internal Server Error',
        message: objectError.length > 0 ? objectError : undefined,
      };
    }
  }
  ```
</CodeGroup>

**Common Causes:**

* Database connection failures
* WhatsApp connection errors
* Unhandled exceptions in business logic
* External service timeouts
* File system errors
* Memory or resource exhaustion

**Example Scenarios:**

<Accordion title="Database Connection Error">
  **Response (500):**

  ```json theme={null}
  {
    "status": 500,
    "error": "Internal Server Error",
    "message": "Database connection failed"
  }
  ```

  Database errors are logged and caught by the error handling middleware.
</Accordion>

<Accordion title="WhatsApp Connection Timeout">
  **Response (500):**

  ```json theme={null}
  {
    "status": 500,
    "error": "Internal Server Error",
    "message": "WhatsApp connection timeout"
  }
  ```
</Accordion>

<Accordion title="Metrics Configuration Error">
  **Request:**

  ```bash theme={null}
  GET /metrics
  Authorization: Basic dXNlcjpwYXNz
  ```

  **Response (500):**

  ```text theme={null}
  Metrics authentication not configured
  ```

  Returned when metrics auth is required but not configured (`src/api/routes/index.router.ts:71-73`).
</Accordion>

## Validation Errors

Evolution API uses JSONSchema7 for request validation (`src/api/abstract/abstract.router.ts:46-60`). Validation errors return detailed information:

### Single Validation Error

```json theme={null}
{
  "status": 400,
  "error": "Bad Request",
  "message": ["number is required"]
}
```

### Multiple Validation Errors

```json theme={null}
{
  "status": 400,
  "error": "Bad Request",
  "message": [
    "number is required",
    "text must be a string",
    "delay must be a number"
  ]
}
```

### Schema Description Override

If the JSONSchema includes a `description` field, it's used as the error message:

```typescript theme={null}
const schema = {
  type: 'object',
  properties: {
    number: {
      type: 'string',
      description: 'Phone number in international format (e.g., 5511999999999)'
    }
  }
};
```

**Error Response:**

```json theme={null}
{
  "status": 400,
  "error": "Bad Request",
  "message": ["Phone number in international format (e.g., 5511999999999)"]
}
```

## Error Handling Best Practices

### Client-Side Error Handling

Implement comprehensive error handling in your client code:

<CodeGroup>
  ```javascript Node.js theme={null}
  async function sendMessage(instanceName, token, number, text) {
    try {
      const response = await fetch(
        `https://api.yourdomain.com/message/sendText/${instanceName}`,
        {
          method: 'POST',
          headers: {
            'apikey': token,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({ number, text })
        }
      );
      
      if (!response.ok) {
        const error = await response.json();
        
        switch (error.status) {
          case 400:
            console.error('Validation error:', error.message);
            // Show user-friendly validation errors
            break;
          case 401:
            console.error('Authentication failed');
            // Redirect to login or refresh token
            break;
          case 404:
            console.error('Instance not found');
            // Prompt user to verify instance name
            break;
          case 500:
            console.error('Server error:', error.message);
            // Retry with exponential backoff
            break;
          default:
            console.error('Unexpected error:', error);
        }
        
        throw error;
      }
      
      return await response.json();
    } catch (error) {
      // Network errors (no response from server)
      if (!error.status) {
        console.error('Network error:', error.message);
        // Implement retry logic
      }
      throw error;
    }
  }
  ```

  ```python Python theme={null}
  import requests
  from typing import Dict, Any
  import time

  def send_message(instance_name: str, token: str, number: str, text: str) -> Dict[Any, Any]:
      url = f'https://api.yourdomain.com/message/sendText/{instance_name}'
      headers = {
          'apikey': token,
          'Content-Type': 'application/json'
      }
      payload = {'number': number, 'text': text}
      
      try:
          response = requests.post(url, json=payload, headers=headers)
          response.raise_for_status()
          return response.json()
      
      except requests.exceptions.HTTPError as e:
          error_data = e.response.json()
          status = error_data.get('status')
          
          if status == 400:
              print(f"Validation error: {error_data['message']}")
          elif status == 401:
              print("Authentication failed - check your API key")
          elif status == 404:
              print(f"Instance '{instance_name}' not found")
          elif status == 500:
              print(f"Server error: {error_data['message']}")
              # Implement retry logic
              time.sleep(2)
              return send_message(instance_name, token, number, text)
          
          raise
      
      except requests.exceptions.RequestException as e:
          print(f"Network error: {e}")
          raise
  ```
</CodeGroup>

### Retry Logic for 500 Errors

Implement exponential backoff for transient server errors:

```javascript theme={null}
async function requestWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 500 && attempt < maxRetries - 1) {
        const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
        console.log(`Retry attempt ${attempt + 1} after ${delay}ms`);
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      
      return response;
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
      
      const delay = Math.pow(2, attempt) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
```

### Logging and Monitoring

Log errors for debugging and monitoring:

```javascript theme={null}
const logError = (context, error) => {
  const logEntry = {
    timestamp: new Date().toISOString(),
    context,
    status: error.status,
    errorType: error.error,
    message: error.message,
    requestId: error.requestId // If your implementation adds request IDs
  };
  
  console.error(JSON.stringify(logEntry));
  
  // Send to monitoring service
  // monitoringService.logError(logEntry);
};
```

## Troubleshooting Common Errors

### "Unauthorized" on Valid Requests

**Symptoms:**

* Receiving 401 errors despite using correct API key
* Authentication works in some environments but not others

**Solutions:**

1. **Check header name**: Ensure you're using `apikey` (lowercase)
   ```bash theme={null}
   # Correct
   apikey: your-token

   # Wrong
   ApiKey: your-token
   API-Key: your-token
   ```

2. **Verify no extra whitespace**: Trim API keys before sending
   ```javascript theme={null}
   const apiKey = process.env.API_KEY.trim();
   ```

3. **Check instance exists**: Verify the instance name is correct
   ```bash theme={null}
   GET /instance/fetchInstances
   apikey: global-key
   ```

4. **Database check**: Ensure instance token matches database record
   ```sql theme={null}
   SELECT name, token FROM Instance WHERE name = 'your-instance';
   ```

### "Bad Request" with Unclear Messages

**Symptoms:**

* Receiving 400 errors with generic validation messages
* Not sure which field is causing the error

**Solutions:**

1. **Enable debug logging**: Check server logs for detailed validation errors
   ```bash theme={null}
   LOG_LEVEL=DEBUG,INFO,WARN,ERROR
   ```

2. **Test with minimal payload**: Start with required fields only
   ```json theme={null}
   {
     "number": "5511999999999",
     "text": "test"
   }
   ```

3. **Validate JSON syntax**: Use a JSON validator to ensure proper formatting

4. **Check data types**: Ensure strings are quoted, numbers are not
   ```json theme={null}
   {
     "number": "5511999999999",  // String
     "delay": 1000               // Number (no quotes)
   }
   ```

### "Instance not found" Immediately After Creation

**Symptoms:**

* Instance creation succeeds (201 response)
* Immediate subsequent requests return 404

**Solutions:**

1. **Check instance name**: Ensure you're using the exact name from creation
   ```javascript theme={null}
   const created = await createInstance({ instanceName: 'test' });
   // Use: created.instance.instanceName
   ```

2. **Wait for initialization**: Add a small delay after creation
   ```javascript theme={null}
   await createInstance({ instanceName: 'test' });
   await new Promise(resolve => setTimeout(resolve, 1000));
   await connectToWhatsApp('test');
   ```

3. **Check database**: Verify instance was persisted
   ```bash theme={null}
   GET /instance/fetchInstances
   apikey: global-key
   ```

### "Internal Server Error" on Message Send

**Symptoms:**

* Message endpoint returns 500 error
* Other endpoints work fine

**Solutions:**

1. **Check instance connection**: Ensure instance is connected to WhatsApp
   ```bash theme={null}
   GET /instance/connectionState/your-instance
   apikey: instance-token
   ```

2. **Verify phone number format**: Use international format without '+'
   ```javascript theme={null}
   // Correct
   { "number": "5511999999999" }

   // Wrong
   { "number": "+55 11 99999-9999" }
   ```

3. **Check server logs**: Look for specific error messages
   ```bash theme={null}
   docker logs evolution-api | grep ERROR
   ```

4. **Test WhatsApp connection**: Try reconnecting the instance
   ```bash theme={null}
   POST /instance/restart/your-instance
   apikey: instance-token
   ```

## Error Logging

Evolution API logs errors using the Logger service (`src/config/logger.config.ts`):

```typescript theme={null}
logger.error(message);  // Logs validation and runtime errors
```

Configure log levels:

```bash theme={null}
LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE
LOG_COLOR=true
LOG_BAILEYS=error  # WhatsApp library logs: fatal, error, warn, info, debug, trace
```

<Note>
  Error logs include timestamps, context, and stack traces for debugging. Monitor logs in production to identify patterns and fix issues proactively.
</Note>

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/api/authentication">
    Learn about API authentication and tokens
  </Card>

  <Card title="API Overview" icon="book" href="/api/overview">
    Return to API overview
  </Card>

  <Card title="Instance Management" icon="server" href="/api/instance/create">
    Create and manage instances
  </Card>

  <Card title="Send Messages" icon="paper-plane" href="/api/messages/send-text">
    Start sending WhatsApp messages
  </Card>
</CardGroup>
