> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sim.dune.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> How to handle errors when using Sim APIs

This guide explains how to handle errors when using Sim APIs, including common error codes, troubleshooting steps, and code examples for proper error handling.

## Errors vs. Warnings

Sim APIs distinguish between **errors** and **warnings**:

* **Errors** indicate that the request failed and could not be fulfilled. The API returns an error response with an HTTP 4xx or 5xx status code.
* **Warnings** indicate non-fatal issues where the request was partially fulfilled. The API returns a successful HTTP 200 response with data, but includes a `warnings` array to inform you about issues that occurred.

### When Warnings Occur

Warnings are currently used when you request data for specific chains via the `chain_ids` parameter and some of those chains are not supported. For example:

* If you request `?chain_ids=1,9999,10` and chain 9999 is not supported, the API will return data for chains 1 and 10, plus a warning about chain 9999.

### Warning Response Format

When warnings are present, they appear in a `warnings` array within the successful (HTTP 200) response:

```json theme={null}
{
  "wallet_address": "0x37305b1cd40574e4c5ce33f8e8306be057fd7341",
  "balances": [...],
  "warnings": [
    {
      "code": "UNSUPPORTED_CHAIN_IDS",
      "message": "Some requested chain_ids are not supported. Balances are returned only for supported chains.",
      "chain_ids": [9999, 77777777777],
      "docs_url": "https://docs.sim.dune.com/evm/supported-chains"
    }
  ]
}
```

Each warning includes:

* `code`: A machine-readable warning code (e.g., `UNSUPPORTED_CHAIN_IDS`)
* `message`: A human-readable description of the warning
* `chain_ids`: The list of chain IDs that caused this warning (for chain-related warnings)
* `docs_url`: A link to relevant documentation for more information

## Error Response Format

Authentication, rate limiting, and quota enforcement errors return JSON with an `error` field:

```json theme={null}
{
  "error": "invalid API Key"
}
```

All other errors return JSON with a `message` field:

```json theme={null}
{
  "message": "Internal server error"
}
```

A few endpoints (EVM Transactions, Activity, Token Info) return errors as plain text with no JSON wrapper.
Check the error responses documented on each endpoint's page for the exact format.

<Note>
  When handling errors programmatically, check for both `"error"` and `"message"` fields in the response body.
</Note>

## Common Error Codes

| HTTP Status | Description                | Troubleshooting                                                                                                         |
| ----------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 400         | Bad request                | Verify the address format and other parameters in your request                                                          |
| 401         | Invalid or missing API key | Check that you're including the correct API key in the `X-Sim-Api-Key` header                                           |
| 402         | Quota limit exceeded       | Your request would exceed your compute unit quota. Contact [sales@dune.com](mailto:sales@dune.com) to upgrade your plan |
| 403         | Forbidden                  | Your API key does not have Sim API permissions. Check your key's assigned permissions                                   |
| 404         | Resource not found         | Verify the endpoint URL and resource identifiers                                                                        |
| 405         | Method not allowed         | The URL path is valid but the HTTP method is not supported. Use the correct method (e.g. GET)                           |
| 429         | Too many requests          | Implement backoff strategies and consider upgrading your plan if you consistently hit limits                            |
| 500         | Internal server error      | Retry the request after a short delay; if persistent, contact support                                                   |
| 502         | Bad gateway                | The service is temporarily unreachable. Retry the request after a short delay                                           |
| 503         | Service unavailable        | The service is temporarily in a retry state. Retry after a short delay                                                  |

## Handling Warnings in Code

When processing API responses, check for the `warnings` array to be notified of non-fatal issues:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    const response = await fetch('https://api.sim.dune.com/v1/evm/balances/0xd8da6bf26964af9d7eed9e03e53415d37aa96045?chain_ids=1,9999,10', {
      headers: {'X-Sim-Api-Key': 'YOUR_API_KEY'}
    });

    const data = await response.json();

    // Check for warnings
    if (data.warnings && data.warnings.length > 0) {
      data.warnings.forEach(warning => {
        if (warning.code === 'UNSUPPORTED_CHAIN_IDS') {
          console.warn(`Warning: Chains ${warning.chain_ids.join(', ')} are not supported.`);
          console.warn(`See: ${warning.docs_url}`);
        }
      });
    }

    // Process the data that was successfully returned
    console.log(`Found ${data.balances.length} balances`);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    response = requests.get(
        'https://api.sim.dune.com/v1/evm/balances/0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
        headers={'X-Sim-Api-Key': 'YOUR_API_KEY'},
        params={'chain_ids': '1,9999,10'}
    )

    data = response.json()

    # Check for warnings
    if 'warnings' in data and len(data['warnings']) > 0:
        for warning in data['warnings']:
            if warning['code'] == 'UNSUPPORTED_CHAIN_IDS':
                print(f"Warning: Chains {warning['chain_ids']} are not supported.")
                print(f"See: {warning['docs_url']}")

    # Process the data that was successfully returned
    print(f"Found {len(data['balances'])} balances")
    ```
  </Tab>
</Tabs>

## Handling Errors in Code

Here are examples of how to properly handle errors in different programming languages:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    fetch('https://api.sim.dune.com/v1/evm/balances/0xd8da6bf26964af9d7eed9e03e53415d37aa96045', {
      method: 'GET', 
      headers: {'X-Sim-Api-Key': 'YOUR_API_KEY'}
    })
      .then(async response => {
        if (!response.ok) {
          // Read response as text first, then try to parse as JSON.
          // Some endpoints return JSON errors, others return plain text.
          const text = await response.text();
          let errorMessage;
          try {
            const err = JSON.parse(text);
            errorMessage = err.error || err.message;
          } catch {
            errorMessage = text;
          }
          throw new Error(`API error (${response.status}): ${errorMessage || response.statusText}`);
        }
        return response.json();
      })
      .then(data => {
        console.log('Success:', data);
      })
      .catch(err => {
        console.error('Error:', err);
      });
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests
    import time

    def get_balances(address, api_key, max_retries=3):
        url = f"https://api.sim.dune.com/v1/evm/balances/{address}"
        headers = {"X-Sim-Api-Key": api_key}
        
        for attempt in range(max_retries):
            try:
                response = requests.get(url, headers=headers)
                response.raise_for_status()  # Raises an exception for 4XX/5XX responses
                return response.json()
                
            except requests.exceptions.HTTPError as err:
                status_code = err.response.status_code
                error_data = {}
                
                # Parse error body. Some endpoints return JSON, others plain text.
                try:
                    error_data = err.response.json()
                    error_message = error_data.get('error') or error_data.get('message', 'Unknown error')
                except ValueError:
                    error_message = err.response.text or 'Unknown error'
                
                print(f"HTTP Error {status_code}: {error_message}")
                
                # Handle specific error codes
                if status_code == 429:  # Rate limit exceeded
                    wait_time = min(2 ** attempt, 60)  # Exponential backoff
                    print(f"Rate limit exceeded. Retrying in {wait_time} seconds...")
                    time.sleep(wait_time)
                    continue
                elif status_code == 500:  # Server error
                    if attempt < max_retries - 1:
                        wait_time = 2 ** attempt
                        print(f"Server error. Retrying in {wait_time} seconds...")
                        time.sleep(wait_time)
                        continue
                
                # For other errors or if we've exhausted retries
                return {"error": error_message, "status_code": status_code}
                
            except requests.exceptions.RequestException as err:
                print(f"Request error: {err}")
                return {"error": "Network or connection error", "details": str(err)}
        
        return {"error": "Max retries exceeded"}

    # Usage
    result = get_balances("0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "YOUR_API_KEY")
    if "error" in result:
        print(f"Failed to get balances: {result['error']}")
    else:
        print(f"Found {len(result['balances'])} token balances")
    ```
  </Tab>
</Tabs>

## Best Practices for Error Handling

1. **Always check for errors**: Don't assume API calls will succeed.

2. **Use HTTP status codes**: Rely on HTTP status codes rather than parsing error message strings for programmatic decisions.

3. **Implement retry logic with backoff**: For transient errors (like rate limits or server errors), implement exponential backoff.

4. **Provide meaningful error messages**: Transform API error responses into user-friendly messages.

5. **Log errors for debugging**: Maintain detailed logs of API errors for troubleshooting.

6. **Implement fallbacks**: When possible, have fallback behavior when API calls fail.

## Debugging Tips

If you're experiencing persistent errors:

1. **Verify your API key**: Ensure it's valid and has the necessary permissions.

2. **Check request format**: Validate that your request parameters match the API specifications.

3. **Inspect full error responses**: The error message often contains specific details about what went wrong.

4. **Monitor your usage**: Check if you're approaching or exceeding rate limits.

5. **Test with cURL**: Isolate issues by testing the API directly with cURL:
   ```bash theme={null}
   curl -v -X GET "https://api.sim.dune.com/v1/evm/balances/0xd8da6bf26964af9d7eed9e03e53415d37aa96045" \
        -H "X-Sim-Api-Key: YOUR_API_KEY"
   ```

## Need More Help?

If you're still experiencing issues after following these guidelines, please reach out through our [support channels](/support).
