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

# Error Handling & Troubleshooting

> Comprehensive guide to error codes, rate limits, retry strategies, and debugging tips for the GoldRush Foundational API.

The GoldRush Foundational API (REST) returns structured errors when something goes wrong. This page is the single reference for understanding error codes, handling rate limits, implementing retries, and debugging common issues.

> [!NOTE]
>
> **Failed requests are free.** No API credits are deducted for any response outside the `2xx` range, whatever the cause. A `429`, a `501`, a `556` and a `500` all cost you nothing, so a retry is never a billing risk.
>
> Retries do still count against your **rate limit**, which is why the guidance below is about backing off correctly rather than about cost.

## Standard and GoldRush-specific codes

Not every code this API returns is a registered HTTP status code. It is worth knowing which is which, because off-the-shelf HTTP clients, proxies and monitoring tools only understand the registered ones and will usually flatten the rest into a generic "5xx".

> [card] Standard HTTP codes
>
> `400` `401` `402` `403` `404` `406` `410` `416` `429` `500` `501` `503` `504` `507`
>
> Registered status codes. Several carry a GoldRush-specific meaning, noted in the table below.

> [card] GoldRush-specific codes
>
> `452` `551` `552` `554` `556` `557` `558` `561` `562` `563` `565` `567` `570`
>
> **Not registered HTTP status codes.** Specific to the GoldRush API. Match on the exact number, not on the `5xx` class.

## The error response body

Every error the API itself generates uses the same envelope as a successful response, with `data` set to `null`:

```json theme={null}
{
  "data": null,
  "error": true,
  "error_message": "This chain does not currently support flag: with-state.",
  "error_code": 501
}
```

Three things to note:

* `error_code` is a **JSON number**, not a string. Compare it with `501`, not `"501"`.
* `error_code` always equals the HTTP status code, so you can branch on either one.
* `error_message` carries the specific reason. Two requests can share a status code and mean entirely different things, so log the message as well as the code.

The one exception is a bare `500`, which is returned with an empty body. Treat a response that has a `5xx` status and no parseable JSON as a `500`.

> [!WARNING]
>
> **A request with no `Authorization` header at all is rejected by the edge proxy, not by the API**, and returns an HTML body rather than JSON:
>
> ```html theme={null}
> <html><head><title>401 Authorization Required</title></head> ...
> ```
>
> A missing or malformed key sent *with* the request returns the normal JSON `401`. If your client parses every response body as JSON, guard this one case, or check the `Content-Type` header before parsing.

## Standard HTTP status codes

These are all registered HTTP status codes. Where our meaning is narrower or more specific than the generic one, it is spelled out here.

| Code | Name | What it means at GoldRush |
| :- | :- | :- |
| `400` | Bad Request | Malformed parameters, invalid address format |
| `401` | Unauthorized | Missing or incorrect API key |
| `402` | Payment Required | Three distinct causes, told apart by `error_message`: credit limit exceeded, a paywalled feature on your tier, or a paused subscription on a production key |
| `403` | Forbidden | API key is valid but not authorized for the resource |
| `404` | Not Found | The endpoint path does not exist, or the specific record (transaction hash, block) was not found. Also returned when a requested block height has not been reached yet on that chain |
| `406` | Not Acceptable | The request would predictably time out with these parameters, so it was not attempted. Reduce the date range or page size and retry |
| `410` | Gone | The endpoint or the chain has been sunsetted. Stop calling it and remove any scheduled jobs that do |
| `416` | Range Not Satisfiable | A query transform supplied with the request failed to parse |
| `429` | Too Many Requests | Rate limit exceeded |
| `500` | Internal Server Error | An unclassified server-side failure. Unlike every other code on this page, a `500` has **no JSON body** |
| `501` | Not Implemented | The chain or endpoint does not support what you asked for. This is the most commonly misread code we return, so it has its own section below |
| `503` | Service Unavailable | The chain is under maintenance, or a backend queue is full |
| `504` | Gateway Timeout | A database query exceeded its statement timeout. Narrow the query and retry |
| `507` | Insufficient Storage | The response was too large to buffer. Reduce `page-size` and retry |

### 501 is a capability answer, not an outage

A `501` means your request was well-formed and your key was fine, but the chain or endpoint cannot serve that particular thing. It is a stable answer rather than a transient one, so retrying it unchanged will not succeed until that support actually ships. It is returned in three situations:

* **An unsupported chain.** Note that an unrecognized chain name returns `501`, not `404`:

  ```json theme={null}
  { "data": null, "error": true, "error_message": "Chain nosuchchain-mainnet not supported.", "error_code": 501 }
  ```

* **A feature flag the chain does not support.** Flags such as `with-state` and `with-input-data` are only available on chains with the underlying data. The flag is valid, the chain just cannot serve it:

  ```json theme={null}
  { "data": null, "error": true, "error_message": "This chain does not currently support flag: with-state.", "error_code": 501 }
  ```

  Rather than discovering this by trial, read the capability flags on [`/v1/chains/`](https://goldrush.dev/docs/api-reference/foundational-api/utility/get-all-chains), such as `is_internal_tx_supported` and `is_input_data_supported`, and skip the call when the flag is false.

* **An endpoint restricted to certain chains**, for example an EVM-only endpoint called on a non-EVM chain.

> [!NOTE]
>
> The gate runs before the identifier is looked up, so a transaction hash that does not exist returns `404` on a chain that supports the flag and `501` on a chain that does not. That makes a throwaway hash a cheap way to test chain support.

## GoldRush-specific status codes

> [!WARNING]
>
> The codes in this section are **not registered HTTP status codes**. They are specific to the GoldRush API.
>
> They exist so that different backend conditions stay distinguishable instead of collapsing into one generic `500`, which is what makes a useful retry policy possible at all. The tradeoff is that generic HTTP tooling does not know them: most clients, proxies and dashboards will report them only as "a 5xx". **Match on the exact number**, and if you alert on error classes, give at least `556` and `565` their own treatment.

All of these carry the normal JSON error body described above.

| Code | `error_message` | What happened | What to do |
| :- | :- | :- | :- |
| `452` | Please un-stealth your User-Agent | Your client sent a browser `User-Agent` but is not a browser | **Do not retry.** Set an honest `User-Agent` that identifies your application, then retry once |
| `551` | Worker thread failed to respond in time | A worker did not finish within its deadline | **Retry with exponential backoff.** If it repeats on the same parameters, the request is probably too broad: narrow the date range or page size |
| `552` | Connection to web3 provider failed | We could not reach the chain's node for a live call | **Retry with exponential backoff**, up to 3 to 5 attempts |
| `554` | Timed out while waiting to acquire a database connection | All pooled database connections were busy | **Retry with exponential backoff.** Transient and usually clears within seconds |
| `556` | Too many concurrent database requests | Deliberate load shedding. The query was refused on purpose to protect a saturated backend | **Retry with exponential backoff, and lower your concurrency.** Do not retry tightly, see the note below |
| `557` | Database replica cancelled query to retain sync with primary | A read replica cancelled the query to stay in sync | **Retry once, immediately.** This one is usually gone on the next attempt |
| `558` | Database unexpectedly closed connection | The connection dropped mid-query | **Retry with exponential backoff**, up to 3 attempts |
| `561` | Could not acquire NFT metadata scraper from pool | The NFT metadata scraping pool was exhausted | **Retry with exponential backoff.** Consider spacing out bulk NFT metadata jobs |
| `562` | Failed to connect to upstream third-party service | A third-party data provider we depend on was unreachable | **Retry with exponential backoff.** Recovery depends on a third party, so allow a longer ceiling, 30 to 60 seconds |
| `563` | Connection to upstream third-party service timed out | A third-party data provider did not answer in time | **Retry with exponential backoff**, same longer ceiling as `562` |
| `565` | Unable to find referenced `<record>` in database; DB has fallen behind web3 source | The record exists on chain but our indexed copy has not caught up. Most often a transaction requested within seconds of being mined | **Wait at least 10 seconds, then retry once.** See the note below, do not retry immediately |
| `567` | Chain dataset is currently unavailable | The dataset for that chain is temporarily not readable | **Retry after 30 seconds or more.** If it persists past a few minutes, treat that chain as down and fail over |
| `570` | Contract execution error during web3 call | The contract call reverted on chain | **Do not retry.** This is a correct answer about the contract, not a failure on our side. Check your call arguments |

> [!TIP]
>
> **`556` is the one to watch.** It means the request was refused on purpose while the backend was under load, not that anything is broken. A burst of `556` is the correct signal to back off; clients that retry it aggressively make the condition worse and last longer.

> [!NOTE]
>
> **`565` is short-lived by design.** The response is cached for only 10 seconds, because the usual cause is that indexing is a few seconds behind the chain tip. Waiting 10 to 15 seconds and retrying once resolves most occurrences. If a `565` for the same record persists for minutes, raise it on the [support page](https://goldrush.dev/platform/support/).

## What to do with every code

Sorted by what the right response actually is, rather than by number.

### Retry with exponential backoff

`429`, `500`, `503`, `504`, `551`, `552`, `554`, `556`, `557`, `558`, `561`, `562`, `563`, `565`, `567`

These are transient. The same request may well succeed later. Use the loop in [Retry Strategies](#retry-strategies) below, with these adjustments:

* **`557`:** retry once immediately before backing off. It usually clears on the next attempt.
* **`565`:** wait at least 10 seconds before the first retry.
* **`562` and `563`:** recovery depends on a third party, so allow a ceiling of 30 to 60 seconds rather than a few seconds.
* **`429`:** back off until your request rate is under the limit for your plan. More attempts will not help.

### Change the request, then retry

`406`, `507`

The request as sent will keep failing, but a narrower one will succeed. Reduce `page-size`, shorten the date range, or split the query, then send it again.

### Fix something, then retry once

`400` fix the parameters. `401` fix the API key. `402` check `error_message` to see which of the three causes applies, then raise your spending limit, upgrade your plan, or resume your subscription. `452` send an honest `User-Agent`.

### Do not retry

`403`, `410`, `416`, `501`, `570`

These are stable answers, not failures in progress. Retrying returns exactly the same thing. `410` means the endpoint or chain is gone for good, so remove the call and any scheduled job that makes it. `501` means the capability does not exist on that chain, so check `/v1/chains/` and skip it. `570` means the contract reverted, which is a real answer about the contract.

> [!NOTE]
>
> **None of this costs credits.** Error responses are not billed, so the cost of a retry is only the rate limit slot it consumes and the latency it adds. Optimize your retry policy for recovery time and for not amplifying an incident, not for spend.

## Rate Limits

The Foundational API enforces rate limits based on your plan tier:

| Plan | Rate Limit | API Credits |
| :- | :- | :- |
| 14-day Free Trial | 4 RPS | 25,000 |
| Vibe Coding (\$10/mo) | 4 RPS | 10,000 |
| Professional (\$250/mo) | 50 RPS | 300,000 |
| Inner Circle | Custom (up to 100+ RPS) | Custom SLA |

Rate limits are enforced **per API key and IP address**. When you exceed your limit, you'll receive a `429 Too Many Requests` response. Back off and retry using the strategies below.

## Retry Strategies

### Exponential Backoff with Jitter

Retry on the transient set only, and use exponential backoff with random jitter so that many clients recovering from the same incident do not retry in lockstep.

A retry loop written against `429`, `500` and `503` alone will miss most of what the API actually returns under load, because the specific codes above are used in preference to a generic `500`. Include them explicitly.

```typescript TypeScript theme={null}
// Transient: a later attempt may succeed with the same request.
const RETRYABLE = new Set([
  429, 500, 503, 504,
  551, 552, 554, 556, 557, 558, 561, 562, 563, 565, 567,
]);

async function fetchWithRetry(
  url: string,
  options: RequestInit,
  maxRetries = 5
): Promise<Response> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.ok) return response;

    if (RETRYABLE.has(response.status)) {
      // 565 means indexing is a few seconds behind the chain tip,
      // so give it a floor of 10s rather than retrying immediately.
      const baseDelay =
        response.status === 565
          ? 10_000
          : Math.pow(2, attempt) * 1000;
      const jitter = Math.random() * 1000;
      await new Promise((r) => setTimeout(r, baseDelay + jitter));
      continue;
    }

    throw new Error(`Request failed: ${response.status}`);
  }

  throw new Error("Max retries exceeded");
}
```

```python Python theme={null}
import time
import random
import requests

# Transient: a later attempt may succeed with the same request.
RETRYABLE = {
    429, 500, 503, 504,
    551, 552, 554, 556, 557, 558, 561, 562, 563, 565, 567,
}

def fetch_with_retry(url, headers, max_retries=5):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)

        if response.ok:
            return response

        if response.status_code in RETRYABLE:
            # 565 means indexing is a few seconds behind the chain tip,
            # so give it a floor of 10s rather than retrying immediately.
            base_delay = 10 if response.status_code == 565 else (2 ** attempt)
            jitter = random.uniform(0, 1)
            time.sleep(base_delay + jitter)
            continue

        response.raise_for_status()

    raise Exception("Max retries exceeded")
```

> [!WARNING]
>
> Never put `403`, `410`, `416`, `501` or `570` in a backoff loop. They are stable answers about the request, the chain or the contract, so every attempt returns the same thing while still consuming a rate limit slot. See [What to do with every code](#what-to-do-with-every-code) for the codes that are worth one retry after you fix something.

### SDK Built-in Retries

The [GoldRush TypeScript Client SDK](https://www.npmjs.com/package/@covalenthq/client-sdk) handles retries and rate limiting automatically - no manual retry logic needed when using the SDK.

## Debugging Tips

> [accordion] Verify your API key format
>
> GoldRush API keys follow the pattern `cqt_wF...` or `cqt_rQ...` (26 base58 characters after the prefix). Double-check for trailing whitespace or truncation.

> [accordion] Check supported chains
>
> An unsupported or misspelled chain returns `501`, not `404`, with `"Chain <name> not supported."` in `error_message`. A `404` on a chain-scoped path usually means the record was not found, not that the chain is wrong. See [Supported Chains](https://goldrush.dev/docs/chains/overview.md) for the full list.

> [accordion] Inspect the full error body
>
> Don't rely on the HTTP status code alone. The JSON response body contains an `error_message` field with specific details about what went wrong. This matters most for `402` and `501`, where one status code covers several unrelated causes that only the message distinguishes.

> [accordion] Test with curl
>
> Isolate issues from your application code by testing directly:
>
> ```bash theme={null}
> # Foundational API
> curl -X GET https://api.covalenthq.com/v1/eth-mainnet/address/demo.eth/balances_v2/ \
>      -u <GOLDRUSH_API_KEY>: \
>      -H 'Content-Type: application/json'
> ```

> [accordion] Monitor credit usage
>
> Track your API credit consumption on the [GoldRush Platform dashboard](https://goldrush.dev/platform) to avoid unexpected `402` errors.

> [accordion] Contact support for persistent server-side errors
>
> If you're consistently hitting `500`, `503`, or any of the GoldRush-specific `5xx` codes after backing off, open a ticket on the [GoldRush support page](https://goldrush.dev/platform/support/) with your API key prefix, the endpoint, the exact `error_code` and `error_message`, and timestamps of the failures.
>
> The support form asks for the endpoint and chain directly, so filing there routes the issue faster than describing it in free text.
>
> Include the exact code. `556` and `565` in particular point at very different causes from a generic `500`, and quoting the number shortens the diagnosis considerably.

## Quick Reference

> [card] [Foundational API Auth](https://goldrush.dev/docs/goldrush-foundational-api/authentication.md)
>
> API key setup, authentication methods, and SDK usage.

> [card] [FAQ](https://goldrush.dev/docs/faq.md)
>
> Common questions about plans, rate limits, and features.

> [card] [Supported Chains](https://goldrush.dev/docs/chains/overview.md)
>
> Full list of supported blockchains and endpoints.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.