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

# Errors & Retries

> Handle API errors and implement retry strategies

## Error Response Format

All API errors follow a consistent JSON structure:

```json theme={null}
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Amount below minimum stake of 0.1 ETH"
}
```

***

## Common Errors

### 400 Bad Request

Client-side errors due to invalid parameters. **Do not retry** — fix the request first.

<AccordionGroup>
  <Accordion title="INSUFFICIENT_BALANCE">
    The user's wallet does not have enough tokens to complete the transaction.

    ```json theme={null}
    {
      "statusCode": 400,
      "error": "INSUFFICIENT_BALANCE",
      "message": "Wallet balance (0.5 ETH) is less than required (1.0 ETH)"
    }
    ```

    **Root cause:** Attempting to stake or deposit more than available balance.

    **Solution:** Check user balance before creating actions. Validate that `balance >= amount + gas`.
  </Accordion>

  <Accordion title="INVALID_AMOUNT">
    Amount is below minimum or above maximum for the yield.

    ```json theme={null}
    {
      "statusCode": 400,
      "error": "INVALID_AMOUNT",
      "message": "Amount below minimum stake of 0.1 ETH"
    }
    ```

    **Root cause:** Not validating against yield metadata before submission.

    **Solution:** Fetch yield metadata and validate `amount >= minDeposit` before calling the action endpoint.
  </Accordion>

  <Accordion title="INVALID_ADDRESS">
    Malformed or incorrectly formatted address.

    ```json theme={null}
    {
      "statusCode": 400,
      "error": "INVALID_ADDRESS",
      "message": "Invalid Ethereum address format"
    }
    ```

    **Root cause:** Copy-paste errors, incorrect network address format, or truncated addresses.

    **Solution:** Validate address format client-side before API calls. Use checksummed addresses for EVM chains.
  </Accordion>
</AccordionGroup>

***

### 401 Unauthorized

API key is missing, expired, revoked, or incorrect. **Do not retry** until authentication is fixed.

```json theme={null}
{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Invalid API key"
}
```

**Common causes:**

* API key not included in `x-api-key` header
* Key was rotated but integration not updated
* Using a test key against production (or vice versa)

**Solution:** Verify the API key is correct and active in your [dashboard](https://dashboard.yield.xyz).

***

### 403 Forbidden

Access denied due to permissions, plan restrictions, or geoblocking.

<Tabs>
  <Tab title="Yield Not Enabled">
    **Most common 403 error.** The requested yield is not activated for your API key.

    ```json theme={null}
    {
      "statusCode": 403,
      "error": "Forbidden",
      "message": "Yield not enabled for this API key"
    }
    ```

    **Root causes:**

    * Trial plan without access to this yield
    * Yield requires approval or enterprise plan
    * Integration not yet activated for your project

    **Solution:** Request yield activation via the dashboard or contact support. Upgrade plan if required.
  </Tab>

  <Tab title="Geoblocking">
    User or request originates from a restricted region.

    ```json theme={null}
    {
      "statusCode": 403,
      "error": "Forbidden",
      "message": "Access denied from US (US-CA)"
    }
    ```

    **Root cause:** Your geoblocking settings restrict this region, or the yield provider restricts access.

    **Solution:** Review geoblocking configuration in dashboard. Some restrictions are protocol-enforced and cannot be overridden.
  </Tab>

  <Tab title="Read-Only Key">
    Attempting a write operation with a read-only API key.

    ```json theme={null}
    {
      "statusCode": 403,
      "error": "Forbidden",
      "message": "Read-only API key cannot create actions"
    }
    ```

    **Solution:** Use a read-write API key for action creation.
  </Tab>
</Tabs>

<Warning>
  **Yield not enabled** is the most frequently reported error in support channels. Always verify your API key has access to the specific yield before integration.
</Warning>

***

### 404 Not Found

The requested resource does not exist.

```json theme={null}
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Yield not found: invalid-yield-id"
}
```

**Common causes:**

* Mistyped or invalid `yieldId`
* Yield has been deprecated or removed
* Using an internal/test yield ID in production

**Solution:** Verify the yield ID exists by querying `GET /v1/yields` or `GET /v1/yields/{yieldId}`.

***

### 429 Rate Limited

Request quota exceeded. **Retry with backoff.**

```json theme={null}
{
  "statusCode": 429,
  "error": "Too Many Requests",
  "message": "Rate limit exceeded",
  "retryAfter": 30
}
```

**Common causes:**

* Automated scripts without throttling
* High-frequency polling during integration testing
* Burst traffic from multiple concurrent requests

**Solution:** Implement exponential backoff. Respect the `retryAfter` value. Consider upgrading your plan for higher limits.

***

### 5xx Server Errors

Temporary server-side issues. **Retry with exponential backoff.**

```json theme={null}
{
  "statusCode": 503,
  "error": "Service Unavailable",
  "message": "Yield temporarily paused"
}
```

**Solution:** Retry with backoff. If errors persist beyond 5 minutes, contact support with error details and timestamps.

***

## Other Frequently Reported Issues

<AccordionGroup>
  <Accordion title="Transaction failures">
    Transactions may fail due to:

    * Expired signatures or tokens
    * Incorrect transaction construction
    * Insufficient gas fees
    * Nonce conflicts

    **Solution:** Refresh credentials, verify transaction construction, ensure sufficient gas, and handle nonce management properly.
  </Accordion>

  <Accordion title="Stale yield data">
    APY or availability data may be temporarily stale during network congestion or protocol updates.

    **Solution:** Implement reasonable caching (5-15 minutes for APY data). Re-fetch before critical operations.
  </Accordion>

  <Accordion title="Cross-chain routing failures">
    Bridge or swap steps may fail due to liquidity or slippage issues.

    **Solution:** Check route availability before executing. Handle partial failures gracefully in multi-step flows.
  </Accordion>
</AccordionGroup>

***

## Retry Strategy

### Which Errors to Retry

| Status Code | Retry?  | Action                                  |
| ----------- | ------- | --------------------------------------- |
| 400         | No      | Fix request parameters                  |
| 401         | No      | Fix API key                             |
| 403         | No      | Check permissions, plan, or geoblocking |
| 404         | No      | Verify resource exists                  |
| 429         | **Yes** | Wait for `retryAfter`, then retry       |
| 5xx         | **Yes** | Exponential backoff                     |

### Exponential Backoff Implementation

```typescript theme={null}
async function fetchWithRetry(
  url: string,
  options: RequestInit,
  maxRetries = 3
): Promise<Response> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      // Rate limited - respect retryAfter
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After');
        const delay = retryAfter 
          ? parseInt(retryAfter) * 1000 
          : Math.pow(2, attempt) * 1000;
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      
      // Server error - exponential backoff
      if (response.status >= 500) {
        const delay = Math.pow(2, attempt) * 1000;
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      
      return response;
    } catch (error) {
      // Network error - retry with backoff
      if (attempt === maxRetries - 1) throw error;
      await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
    }
  }
  
  throw new Error('Max retries exceeded');
}
```

***

## Best Practices

<CardGroup cols={2}>
  <Card title="Validate before calling" icon="check">
    Check balances, amounts, and addresses client-side before API calls
  </Card>

  <Card title="Verify yield access" icon="key">
    Confirm your API key has access to specific yields before integration
  </Card>

  <Card title="Retry only transient errors" icon="arrows-rotate">
    Only retry 429 and 5xx errors. All others require fixes.
  </Card>

  <Card title="Log everything" icon="file-lines">
    Log all errors with timestamps for debugging and support escalation
  </Card>

  <Card title="Show actionable messages" icon="comment">
    Translate API errors into user-friendly guidance
  </Card>

  <Card title="Contact support with details" icon="headset">
    Include error codes, timestamps, and request IDs when escalating
  </Card>
</CardGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Rate Limits" icon="gauge" href="/documentation/plans-limits/rate-limits">
    Understand rate limiting by plan
  </Card>

  <Card title="Contact Support" icon="envelope" href="mailto:hello@yield.xyz">
    Get help with persistent errors
  </Card>
</CardGroup>
