nautechsystems/nautilus_trader · error · anyhow::Error
Failed to borrow {amount} {coin}: {e}
Error message
Failed to borrow {amount} {coin}: {e} What it means
The high-level BybitHttpClient::borrow() wrapper calls the inner borrow endpoint (spot UTA borrow) and wraps any transport/request error into an anyhow error prefixed with the amount and coin, so callers can see which borrow operation failed. The inner {e} contains the actual cause (HTTP error, Bybit error code, auth failure, insufficient borrowable balance, etc.).
Source
Thrown at crates/adapters/bybit/src/http/client.rs:2337
/// - `coin`: The coin to repay (e.g., "BTC", "ETH")
/// - `amount`: Optional amount to borrow. If None, repays all outstanding borrows.
///
/// # Errors
///
/// Returns an error if:
/// - Credentials are missing.
/// - The request fails.
/// - Insufficient collateral for the borrow.
pub async fn borrow_spot(
&self,
coin: &str,
amount: Quantity,
) -> anyhow::Result<BybitBorrowResponse> {
let amount_str = amount.to_string();
self.inner
.borrow(coin, &amount_str)
.await
.map_err(|e| anyhow::anyhow!("Failed to borrow {amount} {coin}: {e}"))
}
/// Repays spot borrows for a specific coin.
///
/// This should be called after closing short spot positions to avoid accruing interest.
///
/// # 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.
/// - The request fails.
/// - Called during the hourly interest-calculation window (mm:04:00-mm:05:30 UTC each hour).
/// - Insufficient spot balance for repayment.View on GitHub (pinned to 18893faf8b)
Solutions
- Read the inner error {e} in the message for the actual Bybit/HTTP cause
- Verify the coin is borrowable and the amount is within available borrow quota (check margin account data first)
- Confirm the API key has margin/borrow permissions enabled on Bybit
- Retry only if the error is transient (network/5xx); handle quota errors by reducing size or funding the position instead
Example fix
// before
let resp = client.borrow("USDT", qty).await?; // panics on quota errors
// after
match client.borrow("USDT", qty).await {
Ok(resp) => { /* use resp */ }
Err(e) => { log::error!("borrow failed: {e}"); /* reduce size or abort */ }
} Defensive patterns
Strategy: try-catch
Validate before calling
let quota = client.get_borrow_quota(coin).await?;
if quota < amount {
return Err(format!("insufficient borrow quota for {coin}: {quota} < {amount}"));
} Try / catch
match client.borrow(coin, qty).await {
Ok(resp) => Ok(resp),
Err(e) => {
log::error!("spot borrow {coin} failed: {e}");
if is_transient(&e) { retry_with_backoff().await } else { Err(e) }
}
} Prevention
- Check borrowable balance/quota before borrowing
- Ensure API keys have margin borrow permissions
- Cap borrow size vs account risk limits
- Distinguish transient (5xx/timeout) from rejection errors before retrying
When it happens
Trigger: Calling borrow() when the account lacks borrow quota, the coin is not borrowable on Bybit spot margin, credentials are invalid, or the HTTP request fails (network down, timeout, 5xx).
Common situations: Automated strategies that borrow to fund short spot positions; borrowing during high volatility when Bybit rejects due to risk limits; expired API key permissions missing the 'Spot' trade/UTA margin scope.
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 repay spot borrow for {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/2339e71e0abede8b.
Report an issue: GitHub.