nautechsystems/nautilus_trader · error · anyhow::Error
Price limit must be less than current price for zero_for_one
Error message
Price limit must be less than current price for zero_for_one swaps
What it means
When quoting a zero_for_one swap (token0 -> token1), the pool price must move DOWN, so the caller-supplied sqrt price limit must be strictly below the current sqrt price. validate_price_limit bails if limit_price_sqrt >= current price_sqrt_ratio_x96, since such a limit would never be crossed and the swap simulation would be invalid.
Source
Thrown at crates/model/src/defi/pool_analysis/profiler.rs:878
zero_for_one: bool,
) -> anyhow::Result<size_estimator::SizeForImpactResult> {
let config = size_estimator::EstimationConfig::default();
size_estimator::size_for_impact_bps_detailed(self, impact_bps, zero_for_one, &config)
}
/// Validates that the price limit is in the correct direction for the swap.
///
/// # Errors
/// Returns error if price limit violates swap direction constraints.
fn validate_price_limit(
&self,
limit_price_sqrt: U160,
zero_for_one: bool,
) -> anyhow::Result<()> {
if zero_for_one {
// Swapping token0 for token1: price must decrease
if limit_price_sqrt >= self.state.price_sqrt_ratio_x96 {
anyhow::bail!("Price limit must be less than current price for zero_for_one swaps");
}
} else {
// Swapping token1 for token0: price must increase
if limit_price_sqrt <= self.state.price_sqrt_ratio_x96 {
anyhow::bail!(
"Price limit must be greater than current price for one_for_zero swaps"
);
}
}
Ok(())
}
/// Processes a mint (liquidity add) event from historical data.
///
/// Updates pool state when liquidity is added to a position, validates ticks,
/// and delegates to internal liquidity management methods.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Pass the correct sentinel: for zero_for_one use the minimum sqrt price limit (e.g. MIN_SQRT_RATIO), for one_for_zero the maximum
- Compute the limit relative to the current price: ensure limit < state.price_sqrt_ratio_x96 for zero_for_one
- Check the zero_for_one flag is not inverted at the call site
- Pass None for sqrt_price_limit_x96 if no specific bound is required
Example fix
// before let quote = profiler.quote_swap(amount, true, Some(current_sqrt_price))?; // after let limit = MIN_SQRT_PRICE_X96; // must be below current price for zero_for_one let quote = profiler.quote_swap(amount, true, Some(limit))?;
Defensive patterns
Strategy: validation
Validate before calling
if zero_for_one {
anyhow::ensure!(limit < profiler.current_sqrt_price(), "limit must be below current price");
} Type guard
fn valid_zero_for_one_limit(limit: U160, current: U160) -> bool { limit < current } Try / catch
match profiler.quote_swap(amount, true, Some(limit)) {
Ok(q) => q,
Err(e) if e.to_string().contains("must be less than current price") => {
profiler.quote_swap(amount, true, Some(MIN_SQRT_PRICE_X96))?
}
Err(e) => return Err(e),
} Prevention
- Use the standard MIN/MAX sqrt-ratio sentinels unless a real bound is intended
- Derive direction-specific limits from the current price
- Double-check the zero_for_one flag matches the token direction
- Prefer None when no limit constraint is needed
When it happens
Trigger: Calling quote_swap with sqrt_price_limit_x96 = Some(limit) where zero_for_one is true and limit >= current sqrt price — commonly passing MIN/MAX sentinel constants on the wrong side, or reusing a limit computed for the opposite direction.
Common situations: Using sqrt price limit constants meant for one_for_zero swaps in zero_for_one direction; passing the current price as the limit (no movement allowed); direction flags inverted when translating from amount-in semantics.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Price limit must be greater than current price for one_for_z
- Cannot quote swap with zero amount
- No liquidity
- Position liquidity {} is less than the requested burn amount
- Invalid tick range: {tick_lower} >= {tick_upper}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9d57582512c7c25a.
Report an issue: GitHub.