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.