nautechsystems/nautilus_trader · error
No price limit returned from OKX
Error message
No price limit returned from OKX
What it means
Raised in `request_price_limit` when OKX returns success but an empty data array, meaning no price-limit record exists for the requested instrument. The adapter requires at least one row and converts the empty result into an error.
Source
Thrown at crates/adapters/okx/src/http/client.rs:2837
///
/// Returns an error if the HTTP request fails or no price limit is returned.
pub async fn request_price_limit(
&self,
instrument_id: InstrumentId,
) -> anyhow::Result<OKXPriceLimit> {
let mut params = GetPriceLimitParamsBuilder::default();
params.inst_id(instrument_id.symbol.inner());
let params = params.build().map_err(|e| anyhow::anyhow!(e))?;
let resp = self
.inner
.get_price_limit(params)
.await
.map_err(|e| anyhow::anyhow!(e))?;
resp.first()
.cloned()
.ok_or_else(|| anyhow::anyhow!("No price limit returned from OKX"))
}
fn option_summary_exp_time(symbol: &str) -> anyhow::Result<Option<String>> {
let parts: Vec<&str> = symbol.split('-').collect();
anyhow::ensure!(
parts.len() >= 5,
"Expected OKX option symbol with expiry, received {symbol}"
);
Ok(Some(parts[2].to_string()))
}
/// Requests the latest index price for the `instrument_id` from OKX.
///
/// # Errors
///
/// Returns an error if the HTTP request fails or no index price is returned.
pub async fn request_index_price(
&self,View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the instrument is actively listed on OKX and its ID is spelled correctly.
- Treat the missing price limit gracefully in the caller (e.g. skip limit checks or use risk-engine defaults).
- Retry after brief backoff if OKX is under maintenance.
- Reload instruments from OKX so the cache only holds live instruments.
Example fix
// before
let limit = client.request_price_limit(&inst_id).await?;
// after
let limit = match client.request_price_limit(&inst_id).await {
Ok(l) => l,
Err(e) if e.to_string().contains("No price limit returned") => return Ok(None),
Err(e) => return Err(e),
}; Defensive patterns
Strategy: fallback
Validate before calling
if !instrument_is_listed_on_okx(&instrument_id) {
log::warn!("price limit unavailable for delisted {instrument_id}; using risk-engine defaults");
return Ok(None);
} Try / catch
let limit = match client.request_price_limit(&inst_id).await {
Ok(l) => Some(l),
Err(e) if e.to_string().contains("No price limit returned") => None,
Err(e) => return Err(e),
}; Prevention
- Fall back to risk-engine default limits when OKX provides none.
- Only query price limits for instruments confirmed live in the cache.
- Distinguish empty results from transport failures; only retry the latter.
- Refresh the instrument cache periodically to drop delisted instruments.
When it happens
Trigger: Calling `request_price_limit` for an instrument that OKX has no price-limit entry for: delisted/expired instrument, spot pair without limit bands, or wrong symbol in configuration.
Common situations: Checking price limits for expired options before order placement; misconfigured instrument IDs; querying during OKX maintenance windows when data is temporarily unavailable.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- No mark price returned from OKX
- OKX only supports L2_MBP order book deltas
- No usable instruments for {instrument_type:?}, cannot initia
- No usable instruments for {instrument_type:?} family {family
- No instruments loaded for configured types {instrument_types
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/cf7d4521b4e63d86.
Report an issue: GitHub.