Starkscan

Retryable API errors

How to handle Starkscan 503 responses and Retry-After without hiding stale or incomplete data.

Retryable API errors

Starkscan uses HTTP 503 when a request is valid but a bounded serving dependency is temporarily unavailable. The response body keeps the standard REST error shape:

{
  "code": "event_key_index_coverage_unavailable",
  "message": "to_block 13978045 exceeds certified coverage for this selector/key position. Highest servable to_block is 13977799.",
  "maxServableToBlock": 13977799,
  "docSlug": "api/retry",
  "requestId": "mzk-..."
}

For GET or HEAD /v1/{chain}/tx/{tx_hash}/trace, a 503 with code=service_unavailable and Retry-After: 1 can mean the live trace in-flight lane is full. Wait at least the indicated delay and reduce concurrent trace requests. The per-key heavy minute budget is separate; a 429 still uses the rate limit guide. Do not treat a trace 503 as an absent transaction or shorten the request timeout for traces that are already running.

A trace 503 with code=transaction_trace_upstream_unavailable means the upstream trace node failed to produce the trace or could not be reached. Starkscan may already have retried some node faults within the request, but the 503 does not mean every retry was exhausted. The same request usually succeeds on a later attempt, so retry after Retry-After. A trace 404 with code=transaction_trace_not_available is different: the node knows the transaction but has not executed it in a block, so it has no trace. That can mean the transaction is still pending or that it was rejected, which never produces a trace. Check the transaction's status before retrying. A trace 404 with code=not_found means the transaction hash is unknown.

A /transfers 503 with code=transfer_invocation_type_scan_timeout does not go away on retry. A rare invocationType (L1_HANDLER, DECLARE, DEPLOY) can scan a long stretch of history before it fills a page. Narrow from_block/to_block to a few thousand blocks, or add an address filter, and page through the windows.

For an entitled positional full-range event request, Starkscan now performs this upper-bound clamp itself and returns HTTP 200; compare rangeCoverage.requestedToBlock with rangeCoverage.completeThroughBlock. Older deployments and requests without a complete prefix can still return this typed 503. When maxServableToBlock is present there, retry once with to_block clamped to that exact value. Use Retry-After only when you need the original higher bound. Do not retry immediately in a tight loop, and do not treat a 503 as an empty result or as proof that an address, event, holder, or balance is absent.

For full-range positional event searches, first read /v1/meta/capabilities. A wide request is eligible only when eventSearch.fullRange.selectorCoverage contains ready coverage for the exact selector and key position, and the requested lower bound is no lower than servableFromBlock. maxServableToBlock is the complete response ceiling; throughBlock is a legacy safe compatibility bound, and tierCertifiedThroughBlock is the actual tier certificate diagnostic. The server can bridge a small moving-head certification lag with a bounded raw head-tail scan while preserving complete cursor pagination. If a request still reaches an uncovered selector/key prefix, prefer the response's maxServableToBlock over re-reading capabilities: it is the highest bound proved for that exact failed request.

If the response code is full_range_selector_not_supported, retrying the same request will not help until capabilities advertise support for that selector and position. If the response is rate_limited, follow the rate limit guide instead.

Retired token-holder routes

Former enumeration, screening, and analytics routes return 410 token_holders_retired. Reconstruct a scoped set from transfer facts if you need a holder analysis; the API no longer publishes a census.

On this page