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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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