nautechsystems/nautilus_trader · error
Derived minimum output is zero for quoted output {quoted_amo
Error message
Derived minimum output is zero for quoted output {quoted_amount_out} at {slippage_bps} bps slippage What it means
After applying slippage, if the derived minimum output rounds down to zero the swap would have no slippage protection (any output accepted). The adapter bails with the quoted output and slippage values to force the caller to use a tighter slippage or larger trade size.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:5295
if !amount.is_negative() {
anyhow::bail!("Swap quote output amount {amount} is not a positive output");
}
Ok(amount.unsigned_abs())
}
/// Derives the minimum output accepted for the swap: the quoted output reduced by
/// `slippage_bps`, in exact integer arithmetic. Rejects a zero minimum, which would leave
/// the swap without slippage protection.
fn derive_min_amount_out(quoted_amount_out: U256, slippage_bps: u32) -> anyhow::Result<U256> {
if slippage_bps >= BPS_DENOMINATOR {
anyhow::bail!("Slippage {slippage_bps} bps must be below {BPS_DENOMINATOR}");
}
let min_amount_out = quoted_amount_out
.checked_mul(U256::from(BPS_DENOMINATOR - slippage_bps))
.and_then(|scaled| scaled.checked_div(U256::from(BPS_DENOMINATOR)))
.ok_or_else(|| anyhow::anyhow!("Minimum output derivation overflow"))?;
if min_amount_out.is_zero() {
anyhow::bail!(
"Derived minimum output is zero for quoted output {quoted_amount_out} at {slippage_bps} bps slippage"
);
}
Ok(min_amount_out)
}
impl BlockchainExecutionClient {
async fn build_execution_verification_migration(
&self,
snapshot: ExecutionVerificationMigrationSnapshot,
finalized: VerifiedBlockHeader,
finalized_headers: &[VerifiedBlockHeader],
nonce_verification: &Verified<u64>,
) -> anyhow::Result<ExecutionVerificationMigration> {
let next_canonical_nonce = nonce_verification.value;
let mut hashes_by_intent: HashMap<i64, Vec<&ExecutionTransactionHashRow>> = HashMap::new();
for hash in &snapshot.hashes {
hashes_by_intentView on GitHub (pinned to 18893faf8b)
Solutions
- Reduce slippage_bps so the derived minimum stays positive
- Increase the trade size; the quoted output is too small to protect
- Treat as dust and skip the trade; failing open with min 0 is unsafe
Example fix
// before let min_out = derive_min_amount_out(U256::from(3u8), 5000)?; // -> 0 // after let min_out = derive_min_amount_out(U256::from(3_000_000u32), 100)?; // keep min > 0
Defensive patterns
Strategy: validation
Validate before calling
let bps = slippage_bps.min(9_999);
if quoted_amount_out * U256::from(BPS_DENOMINATOR - bps) < U256::from(BPS_DENOMINATOR) {
return Err(anyhow::anyhow!("quote too small for slippage; min would round to 0"));
} Try / catch
match derive_min_amount_out(quoted, bps) {
Ok(min) => swap(min),
Err(e) if e.to_string().contains("is zero") => skip_dust_trade(),
Err(e) => return Err(e),
} Prevention
- Pre-check quoted output magnitude against slippage before submitting
- Never accept min_amount_out == 0; skip or resize the trade
When it happens
Trigger: derive_min_amount_out with a very small quoted_amount_out relative to slippage_bps, e.g. quoted output of a few wei with 1000+ bps slippage, so quoted * (10000-bps) / 10000 truncates to 0.
Common situations: Tiny dust-sized swaps; extremely wide slippage tolerance on a small quote; illiquid pool returning near-zero quotes.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- {type_name} raw value {raw} exceeds {raw_max_name}={raw_max}
- Slippage {slippage_bps} bps exceeds the configured `max_slip
- Slippage {slippage_bps} bps must be below {BPS_DENOMINATOR}
- {type_name} amount {amount} overflows U256 while scaling fro
- Pool {instrument_id} fee {fee} exceeds uint24
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7b373cb90955dfbc.
Report an issue: GitHub.