HTTP 403 on Solana RPC, and the site that could not reach the extension
- tags
- #incident#incidents
- date
- 2026-10-06
- reading
- 3 min · 557 words
- links
- 0 out · 0 in
Status: fixed in code (438cd25, a05b905), pending confirmation in the browser.
Symptom
The browser showed Solana error #8100002. Decoded, it is
SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR { statusCode: 403, headers, message: "" }: an HTTP 403
on an RPC request, not an on-chain failure.
Root cause (from the code)
Only /shield used the same-origin proxy (/api/solana-rpc → RPC Fast). These paths called
https://api.mainnet-beta.solana.com directly from the browser:
/wallet(WalletSession.check);/pay(createPaymentFlow);- the default
unlock().
The public endpoint answers browser requests with 403. Kit wraps that into #8100002.
This is inference from the code, not a reproduction. Vercel keeps runtime logs for 1 h on this plan, so the original request is gone. It is the only call path that matches the symptom.
The proxy itself could also answer 403, for a disallowed origin or a method outside the allowlist. The two were indistinguishable before.
Fix
solanaRpc(stage)is the only client RPC. On the deployed site it is the same-origin proxy, traced per request.- The proxy tags every response
x-upay3food-rpc-layer: proxyand every refusalx-upay3food-rpc-reason. Reasons:origin-not-allowed,method-not-allowed,upstream-auth,upstream-rate-limited,upstream-timeout,upstream-unreachable,not-configured. - Kit keeps response headers in #8100002, so
classifyFailure()can name the layer:
| Class | Meaning |
|---|---|
RPC_PROXY_ORIGIN_403 |
our proxy refused the page's Origin |
RPC_PROXY_METHOD_403 |
our proxy refused a JSON-RPC method |
VERCEL_PROTECTION_403 |
401/403 for the same-origin path without our marker (in front of the proxy) |
PUBLIC_RPC_403 |
a public endpoint refused the browser |
RPC_UPSTREAM_AUTH_FAILURE |
RPC Fast rejected the proxy's credentials |
RPC_RATE_LIMIT |
429 |
RPC_NETWORK_FAILURE |
no HTTP answer, upstream timeout/unreachable |
RPC_PROXY_NOT_CONFIGURED |
RPC_FAST_URL missing |
WALLET_PROVIDER_FAILURE / CLOAK_RELAY_FAILURE |
not the RPC at all |
GET /api/solana-rpc/healthrunsgetHealth,getGenesisHashandgetSlotthrough the same forwarding path. It is read-only and returns fixed fields only./diagnosticsshows:- proxy, upstream and network;
- a
getSlotsent from the browser; - wallet detected and abbreviated address (silent reconnect, no prompt);
- Cloak relay
/health; - a live RPC trace (method, status, JSON-RPC code, time, class; never URLs, params or signed bytes).
Verified on the live site (2026-10-06): upay3food.com/api/solana-rpc/health answered proxy OK,
upstream (RPC Fast) OK, mainnet-beta, slot 453 756 901, 290 ms.
Second finding: the site could not talk to the extension
externally_connectablein the extension manifest listed onlylocalhost/127.0.0.1. Chrome therefore gavehttps://upay3food.comnochrome.runtime.sendMessageto the extension at all.- The background accepted only the origin of
settings.fundingAppUrl, whose default washttp://localhost:3000/pay.
Fix:
- the manifest and
TRUSTED_WEB_ORIGINSlisthttps://upay3food.com. No wildcard, nodocs., no previews;wwwredirects to the apex. A test keeps the two in sync. - the default
fundingAppUrlishttps://upay3food.com/pay. PING/GET_CONNECTIVITYreport each link: background up, iFood content script answering with its page context only, agent-api configured (origin only), executor registered, last poll.pingExtension()names the failing link:NO_EXTENSION_ID,CHROME_RUNTIME_UNAVAILABLE,EXTENSION_NOT_FOUND,ORIGIN_REJECTED,TIMEOUT.
Still open
agent-apiis not deployed (noAGENT_API_URLon the project). The run loop web → agent → extension → iFood → agent → web cannot be proven outside localhost yet.- Confirm in the browser that
/walletno longer produces #8100002 (/diagnosticsRPC trace).
Linked mentions 0
No other note links here yet.