nautechsystems/nautilus_trader · error · anyhow::Error
Failed to repay spot borrow for {coin}: {e}
Error message
Failed to repay spot borrow for {coin}: {e} What it means
The no-convert spot repay wrapper calls the inner no_convert_repay endpoint and maps any request error into an anyhow error naming the coin. After the request succeeds, ensure_repay_accepted additionally validates the result status. This error is the map_err wrapper, so {e} holds the underlying cause (HTTP failure, Bybit rejection like insufficient balance, auth error).
Source
Thrown at crates/adapters/bybit/src/http/client.rs:2366
///
/// # Errors
///
/// Returns an error if:
/// - Credentials are missing.
/// - The request fails.
/// - Called during the hourly interest-calculation window (mm:04:00-mm:05:30 UTC each hour).
/// - Insufficient spot balance for repayment.
pub async fn repay_spot_borrow(
&self,
coin: &str,
amount: Option<Quantity>,
) -> anyhow::Result<BybitNoConvertRepayResponse> {
let amount_str = amount.as_ref().map(|q| q.to_string());
let response = self
.inner
.no_convert_repay(coin, amount_str.as_deref())
.await
.map_err(|e| anyhow::anyhow!("Failed to repay spot borrow for {coin}: {e}"))?;
Self::ensure_repay_accepted(coin, response.result.result_status)?;
Ok(response)
}
/// Repays spot borrows for a specific coin, converting other assets if required.
///
/// Unlike [`Self::repay_spot_borrow`], this uses the venue's manual repay endpoint,
/// which may draw on other holdings when the debt coin's spot balance is insufficient.
///
/// # Parameters
///
/// - `coin`: The coin to repay (e.g., "BTC", "ETH")
/// - `amount`: Optional amount to repay. If None, repays all outstanding borrows.
///
/// # Errors
///
/// Returns an error if:
/// - Credentials are missing.View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the embedded {e} for the concrete HTTP/Bybit error code
- Check the outstanding borrow amount for the coin and repay only up to it
- Verify API key permissions for UTA spot margin repay
- Retry on transient network/5xx errors; surface non-retryable rejections to the operator
Example fix
// before
client.no_convert_repay(coin, Some("100".into())).await?;
// after
if let Err(e) = client.no_convert_repay(coin, Some("100".into())).await {
log::error!("repay {coin} failed: {e}");
// fetch outstanding liability and retry with a valid amount
} Defensive patterns
Strategy: try-catch
Validate before calling
let liability = client.get_outstanding_borrow(coin).await?;
if liability == 0 { return Ok(()); } // nothing to repay
let amt = amount.min(liability); Try / catch
if let Err(e) = client.no_convert_repay(coin, amount).await {
log::error!("repay {coin} failed: {e}");
// re-query liability, adjust amount, retry once
} Prevention
- Query outstanding liability before each repay
- Never repay more than the current borrow
- Keep repay permissions on the API key
- Handle Bybit maintenance windows with backoff
When it happens
Trigger: Calling repay_spot_borrow_no_convert when the HTTP request fails, the API key lacks permissions, the amount exceeds the outstanding borrow, or Bybit rejects the repay order for that coin.
Common situations: End-of-position cleanup code repaying spot borrows; repaying more than the current liability; Bybit maintenance windows or 5xx errors; API key rotation dropping required scopes.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- Failed to borrow {amount} {coin}: {e}
- Failed to repay spot borrow (with conversion) for {coin}: {e
- Bybit repay for {coin} returned result status {status}
- Modify order failed: {e}
- Either client_order_id or venue_order_id is required
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/be92608cae8d60df.
Report an issue: GitHub.