{"record":{"id":"8082fc9df69c276d","repo":"jamiepine/voicebox","slug":"rpc-method-http-res-status","errorCode":null,"errorMessage":"RPC ${method} HTTP ${res.status}","messagePattern":"RPC (.+?) HTTP (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"landing/src/lib/token-stats.ts","lineNumber":269,"sourceCode":"    marketCapUsd,\n    creatorRewardsSol,\n    creatorRewardsUsd,\n    circulating,\n    updatedAt: Date.now(),\n    warnings,\n  };\n}\n\n// ── Solana / Helius RPC primitives ───────────────────────────────────────────\n\nasync function rpcCall<T>(rpc: string, method: string, params: unknown): Promise<T> {\n  const res = await fetch(rpc, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    next: { revalidate: REVALIDATE_S },\n    body: JSON.stringify({ jsonrpc: '2.0', id: 'voicebox', method, params }),\n  });\n  if (!res.ok) throw new Error(`RPC ${method} HTTP ${res.status}`);\n  const json = (await res.json()) as { result?: T; error?: { message: string } };\n  if (json.error) throw new Error(`RPC ${method}: ${json.error.message}`);\n  if (json.result === undefined) throw new Error(`RPC ${method}: empty result`);\n  return json.result;\n}\n\ninterface SupplyResult {\n  value: { amount: string; decimals: number; uiAmount: number | null };\n}\nasync function getTokenSupply(\n  rpc: string,\n): Promise<{ uiAmount: number; decimals: number }> {\n  const r = await rpcCall<SupplyResult>(rpc, 'getTokenSupply', [MINT]);\n  const decimals = r.value.decimals;\n  const uiAmount =\n    r.value.uiAmount ?? Number(r.value.amount) / 10 ** decimals;\n  return { uiAmount, decimals };\n}","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/landing/src/lib/token-stats.ts#L251-L287","documentation":"Thrown by `rpcCall()` in `landing/src/lib/token-stats.ts` (line 269) when a Solana/Helius JSON-RPC POST returns a non-2xx HTTP status, before the body is even parsed. The endpoint is configurable (a public mainnet RPC fallback or a Helius keyed URL). The whole token-stats module is designed to 'never throw' — each sub-fetch is isolated and failures degrade that metric to `null` plus a `warnings` entry — so this error is caught one level up and never reaches the page.","triggerScenarios":"RPC endpoint is down or returning 5xx; the Helius URL has a missing/invalid API key -> 401; the public RPC rate limit hit -> 429; the configured `rpc` string is malformed or points at the wrong network (e.g. devnet) returning 404; CORS/network failure reaching the RPC host.","commonSituations":"Helius API key not set or revoked so keyed calls 401; public mainnet RPC rate-limited under load (the 10-min cache usually prevents this but a cold cache under concurrent requests can exceed it); wrong `rpc` env var after a deploy; RPC provider incident.","solutions":["Verify the `rpc` URL resolves to the intended network and, for Helius, that the API key is valid and set in the env.","On 429 from the public RPC, switch to a keyed Helius endpoint with higher limits and rely on the existing ISR cache to stay under quota.","On 401, rotate/regenerate the Helius key and redeploy.","On 5xx, fall back to the alternate RPC — the module already isolates failures, so add a secondary RPC URL and retry once."],"exampleFix":"// before\nconst res = await fetch(rpc, { method: 'POST', ... });\nif (!res.ok) throw new Error(`RPC ${method} HTTP ${res.status}`);\n\n// after — retry once against a fallback RPC on transport errors\nasync function rpcCall<T>(rpc: string, fallback: string | undefined, method: string, params: unknown) {\n  for (const url of [rpc, fallback].filter(Boolean) as string[]) {\n    try {\n      const res = await fetch(url, { method:'POST', headers:{'Content-Type':'application/json'}, next:{revalidate:REVALIDATE_S}, body: JSON.stringify({jsonrpc:'2.0',id:'voicebox',method,params}) });\n      if (res.ok) return (await res.json()).result as T;\n    } catch { /* try next */ }\n  }\n  throw new Error(`RPC ${method} failed on all endpoints`);\n}","handlingStrategy":"fallback","validationCode":"// Prefer a keyed Helius endpoint; validate the URL before use\nfunction resolveRpc(): string {\n  const keyed = process.env.HELIUS_RPC_URL;\n  if (keyed && /^https:\\/\\//.test(keyed)) return keyed;\n  return PUBLIC_MAINNET_RPC; // public fallback\n}","typeGuard":"function isRpcHttpError(e: unknown): boolean {\n  return /RPC .* HTTP \\d+/.test(String((e as Error)?.message ?? ''));\n}","tryCatchPattern":"// The module already isolates failures — mirror that pattern\ntry {\n  return await rpcCall(rpc, method, params);\n} catch (e) {\n  warnings.push(`${method}: ${(e as Error).message}`);\n  return null; // degrade this metric, keep the page rendering\n}","preventionTips":["Set a valid Helius API key (or another keyed RPC) to avoid public-RPC 429s.","Add a secondary RPC and retry once on transport errors.","Rely on the existing ISR cache to stay under rate limits.","Never let a single RPC failure crash the page — always degrade to null + warning."],"tags":["solana","rpc","helius","network","landing","rate-limit"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}