Skip to content

Aptos and Soroban REST calls ignore HTTP status codes — error bodies displayed as valid data #2

Description

@Kingvic300

Description

For their REST-based (non-JSON-RPC) endpoints, both AptosAdapter and SorobanAdapter parse the response body as JSON and return it unconditionally, without ever checking response.status():

  • cli/src/chains/aptos.rs: get_balance (63-67), get_transaction (69-73), get_block (75-86), get_gas_price (88-91), get_account (93-97), get_history (99-107) — all do Ok(self.client.get(url).send().await?.json().await?) with no status check.
  • cli/src/chains/soroban.rs: get_balance (84-89), get_account (110-115), get_history (117-126) — same pattern against the Horizon REST API.

Neither the Aptos REST API nor Horizon return non-JSON bodies on error (both return a JSON object with an error message/code even on 400/404), so response.json() succeeds and the error payload is returned as Ok(...).

Verified

reqwest::Response::json() parses the body regardless of status code; it only errors if the body isn't valid JSON. Since Aptos/Horizon error responses ARE valid JSON, e.g. Aptos returns {"message":"Account not found by Address(...)","error_code":"account_not_found",...} with HTTP 404 — this flows straight through as a "successful" Result<Value>. Concretely, in cli/src/cli/handlers.rs's Balance handler (line ~548-578), the Aptos branch scans the returned array for a CoinStore resource; when the value is actually an error object (not an array), result.as_array() is None, found stays false, and it falls through to Self::print_value(&result, pretty) — printing the raw Aptos error JSON with a success exit code, no "Error:" prefix, no indication the address lookup failed. The same applies to Soroban get_balance/get_account/get_history against Horizon.

Suggested fix

Add a status check before/instead of blindly parsing, e.g.:

let response = self.client.get(url).send().await?;
let status = response.status();
let body: Value = response.json().await?;
if !status.is_success() {
    let msg = body.get("message").and_then(|m| m.as_str()).unwrap_or("Unknown error");
    return Err(anyhow!("{msg} (HTTP {status})"));
}
Ok(body)

applied consistently to every REST call site in aptos.rs and soroban.rs.

Timeframe

Claim window: 96 hours. If this issue is claimed/assigned, please submit a fix within 96 hours of assignment — after that window it may be released back up for grabs.

Community

Questions about this issue or the campaign? Join https://t.me/txioCommunity

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26Third CampaignCampaign: Third CampaignbugSomething isn't workingpriority:highShould be next

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions