unionlabs/union · warning · RpcStatusError
Malformed response
Error message
Malformed response
What it means
RpcStatusError thrown after a successful HTTP 200 from a Cosmos RPC probe: the JSON-RPC response parsed fine, but data.result.sync_info and/or data.result.node_info are missing, so the payload is not shaped like a CometBFT "status" result. The offending payload is attached to the error for inspection.
Source
Thrown at app2/src/routes/nodes/+page.svelte:82
if (type === "cosmos") {
const { result: res, duration } = await withTiming(async () =>
fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "status",
params: [],
}),
})
)
if (!res.ok) {
throw new RpcStatusError("cosmos", url, `HTTP ${res.status} - ${res.statusText}`)
}
const data = await res.json()
if (!(data?.result?.sync_info && data?.result?.node_info)) {
throw new RpcStatusError("cosmos", url, "Malformed response", data)
}
return {
url,
type: "cosmos",
responseTimeMs: duration,
status: {
kind: "cosmos",
latestBlockHeight: Number(data.result.sync_info.latest_block_height),
catchingUp: data.result.sync_info.catching_up,
moniker: data.result.node_info.moniker,
network: data.result.node_info.network,
},
}
}
if (type === "evm") {
const { result: res, duration } = await withTiming(async () =>
fetch(url, {
method: "POST",View on GitHub (pinned to 031785bb6d)
Solutions
- Check the attached data payload: if it has an error field, fix the underlying JSON-RPC problem (method/rate limit/auth)
- Move the URL to the correct list (EVM endpoints belong to the eth_blockNumber probe)
- Use a real CometBFT RPC endpoint (port 26657) that supports the "status" method
Defensive patterns
Strategy: type-guard
Validate before calling
const data = await res.json()
const isCosmosStatusResult = (d: unknown): d is { result: { sync_info: unknown; node_info: unknown } } =>
typeof d === "object" && d !== null &&
"result" in d &&
typeof (d as any).result === "object" &&
(d as any).result !== null &&
"sync_info" in (d as any).result &&
"node_info" in (d as any).result
if (!isCosmosStatusResult(data)) {
// classify: EVM node vs JSON-RPC error, then mark endpoint misconfigured
} Type guard
const isCosmosStatusPayload = (d: any): d is { result: { sync_info: { latest_block_height: string; catching_up: boolean }; node_info: { moniker: string; network: string } } } =>
Boolean(d?.result?.sync_info && d?.result?.node_info) Try / catch
try {
status = await checkCosmos(url)
} catch (error) {
if (error instanceof RpcStatusError && error.message === "Malformed response") {
// inspect error.data: presence of .error means RPC-level failure; a hex .result means it is an EVM endpoint
}
throw error
} Prevention
- Validate response shape (result.sync_info + node_info) before parsing fields
- Keep Cosmos and EVM endpoint lists separate and type-tag them
- Check the JSON-RPC error field whenever HTTP 200 still yields no result
When it happens
Trigger: POSTing {method:"status"} to an endpoint that returns 200 with a different body shape: an EVM JSON-RPC node (returns {result:"0x..."}), a JSON-RPC error object {error:{...}}, a REST/LCD gateway, or an HTML/JSON welcome page from a proxy.
Common situations: Mixing up node types when adding URLs to the status checker (an Ethereum RPC in the Cosmos list); endpoints fronted by proxies that rewrite responses; JSON-RPC errors (rate limit, invalid method) that still use HTTP 200.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Missing result field
- HTTP ${res.status} - ${res.statusText}
- Invalid gas price string
- NOT IMPLEMENTED
- Invalid Sui signer: expected Ed25519Keypair
AI-assisted analysis of unionlabs/union@031785bb6d (2026-08-16).
Data as JSON: /api/errors/59c1349320b1763d.
Report an issue: GitHub.