Why TON RPC calls fail with "not in db"
Last updated:
At a glance
| Property | Value |
|---|---|
| What you get back | JSON-RPC -32602 with beyond_retention/oldest N, or a plain liteserver message ("not in db", "block not in db", "state not in db") |
| Error field present | Yes — an explicit failure, not a successful-but-empty result like the sibling pilot pages above |
| Cause | The seqno is below the retention floor of the specific liteserver that answered — a per-node, best-effort boundary, not a network-wide one |
| Does retrying help | Sometimes — the pool can route a retry to a different liteserver that still retains the seqno; retrying against the same, already-pruned node never helps |
| Same -32602 code also means | Malformed named parameters — the code alone does not distinguish the two causes |
What you see
You call a TON JSON-RPC method that takes a historical seqno — getBlock, getBlockHeader, getAddressInformation, getConfigAll, getConfigParam, or lookupBlock — for a seqno that looks entirely valid: it is numerically below the current masterchain seqno, and it may even be one you read successfully a few minutes earlier. Instead of a result, the call fails. Sometimes that is the JSON-RPC envelope: code -32602, with a message carrying "beyond_retention" and "oldest N". Other times it is plain liteserver text that is not folded into any structured field at all — "not in db", "block not in db", or "state not in db". Either way this is not a silent, successful-but-empty result; TON reports it as an explicit failure. And it is not consistent: sending the identical request again, unchanged, can succeed where it just failed.
Why this happens
TON's seqno-scoped read methods run over a pool of ADNL liteservers rather than one database. Each request is answered by whichever liteserver the pool selects, and historical availability is a per-liteserver property: archive routing is best-effort and does not turn the pool into a continuous full-history service. A liteserver that has pruned a given seqno keeps reporting the same retention boundary for it no matter how many more times the identical request reaches that same liteserver — TON's own error reference is direct that retrying a historical request against nodes that have pruned the data cannot make it available. What can change the outcome is not repetition against that one node, but the pool selecting a different node on the next request: the getConfigAll reference documents a historical read that "can fail even when a different node can answer the same sequence." A retry that happens to land on a liteserver that has not pruned the seqno can succeed exactly where the first attempt, landing on one that had, could not. Both failure shapes come from the same boundary: TON's error reference classifies the raw liteserver messages ("not in db" and its variants) as the identical retention boundary as the structured -32602/beyond_retention/oldest-N response, not as something rewritten into an empty result. The -32602 code itself is overloaded, though — it is also returned for a request with malformed named parameters, so the code alone does not tell you which situation you are in; you need beyond_retention/oldest N, or a liteserver message pattern, to know it is retention rather than a broken request. This also makes the boundary itself different in kind from a single node's own storage limit (the kind an individual Solana or Stellar node enforces): there, the same node keeps answering every retry, so retrying the identical call never changes the answer. In a liteserver pool, which node answers can change between two otherwise identical calls, which is why the same seqno can look available one moment and gone the next with nothing about your request having changed.
What to do
- Read the failure body, not just the -32602 code: look for beyond_retention and oldest N in a structured JSON-RPC error, or a plain liteserver message such as "not in db", "block not in db", or "state not in db" — either pattern means a retention boundary, not a malformed request.
- Rule out the other cause of the same -32602 code first: if the response carries neither beyond_retention/oldest N nor a liteserver message pattern, treat it as a malformed request — a missing required coordinate (workchain/shard/seqno) or a wrong parameter shape — rather than retention.
- A single retry can be worth sending: node selection happens per request, and a retry may land on a liteserver that has not pruned the seqno the first one had. Do not loop retries expecting the same exhausted node to change its answer — repeating the request against a liteserver that has already pruned the data will not make it available.
- Do not treat one successful read of a seqno as a standing guarantee for a later call. Retention is enforced per liteserver and can change between requests, so re-fetching the same seqno later is not guaranteed just because it worked once.
- If a seqno keeps failing across several separate attempts, treat that as a real boundary for the pool as currently composed — a stopping condition, not a reason to keep retrying indefinitely.
When this is not our problem
A retention response here is not a Triport-side bug to report: it reflects which liteserver in the pool happened to answer your request at that moment, and the underlying behavior — independent, best-effort pruning across a set of liteservers rather than one canonical archive — is how reading TON's historical state through a liteserver pool works, not something particular to Triport's routing. There is no single node to fix, and no one fixed retention number Triport could publish here that would stay true across the whole pool or hold steady over time.
FAQ
- Is a "not in db" or beyond_retention response from TON an error in my request?
- Not necessarily. It usually means the seqno you asked for is below the retention floor of the particular liteserver your request happened to reach — a boundary, not a malformed call. The same -32602 code is also returned for malformed named parameters, so check for beyond_retention/oldest N, or a liteserver message pattern, before assuming which cause applies.
- If I retry the same request, will it succeed?
- It might, once. TON's read pool selects a liteserver per request, and a retry can land on one that has not pruned the seqno the first attempt's liteserver had. Retrying the identical request against a liteserver that has already pruned the data will not make it available — TON's own error reference is explicit about that — so treat a single retry as worth trying, not as a loop to run indefinitely.