nautechsystems/nautilus_trader · error · anyhow::Error

failed to request AX whoami

Error message

failed to request AX whoami

What it means

During fee resolution (request_account_fees, called when the execution client builds account state at connect), the whoami REST call failed and its AxHttpError is wrapped with the context 'failed to request AX whoami'. Whoami is the identity endpoint that enumerates the accounts and fee tiers your credentials cover; failure here means the request never yielded a usable response - auth token missing/expired, network error, rate limit, or a venue 5xx - so maker/taker fee rates cannot be resolved and connect aborts.

Source

Thrown at crates/adapters/architect_ax/src/http/client.rs:1393

    ///
    /// AX reports fee rates per account rather than per user, and returns the accounts the
    /// credentials can act on. The first entry is used, which is the account AX resolves when a
    /// request carries no explicit selector. The rates are retained so later instrument requests,
    /// including the periodic refresh, keep reporting them.
    ///
    /// Requires an authenticated client.
    ///
    /// # Errors
    ///
    /// Returns an error if the request fails, the response carries no accounts, or the selected
    /// account supplies no fee rates. An absent rate is not treated as zero, because a zero rate
    /// is itself valid and a silent zero would outlive the response that caused it.
    pub async fn request_account_fees(&self) -> anyhow::Result<(Decimal, Decimal)> {
        let whoami = self
            .inner
            .get_whoami()
            .await
            .map_err(|e| anyhow::anyhow!(e))
            .context("failed to request AX whoami")?;

        let Some(account) = whoami.accounts.first() else {
            anyhow::bail!("AX whoami returned no accounts to resolve fees from");
        };

        if whoami.accounts.len() > 1 {
            log::warn!(
                "AX credentials cover {} accounts, using fee rates from {}",
                whoami.accounts.len(),
                account.id,
            );
        }

        let (Some(maker_fee), Some(taker_fee)) = (account.maker_fee, account.taker_fee) else {
            anyhow::bail!("AX whoami account {} supplied no fee rates", account.id);
        };

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Read the inner error string to classify: 401/403 -> credential/token problem; network -> connectivity; 429 -> back off and retry connect
  2. Retry engine start once after a short delay; whoami is a cheap idempotent GET
  3. If persistent, verify the key with a direct whoami curl from the same host
  4. Check Architect status/maintenance windows for 5xx bursts
Defensive patterns

Strategy: retry

Try / catch

// request_account_fees at connect: classify and retry transient causes
for attempt in 0..3 {
    match client.request_account_fees().await {
        Ok(fees) => break Ok(fees),
        Err(e) if e.to_string().contains("whoami") && is_transient(&e) => {
            tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await;
        }
        Err(e) => break Err(e),
    }
}

Prevention

When it happens

Trigger: Connecting the AX execution client when the bearer token is invalid (auth raced or failed), the REST endpoint is unreachable, a 429 was returned, or the venue errored (5xx) precisely when fees were being resolved.

Common situations: Intermittent egress problems that only surface on the extra whoami call; rate-limited startups where many clients connect at once; token TTL expiring during a long connect sequence.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/f7cb1d74528e0531. Report an issue: GitHub.