nautechsystems/nautilus_trader · error · anyhow::Error
invalid fee amount='{amount}': {e}
Error message
invalid fee amount='{amount}': {e} What it means
Thrown while parsing a Binance Futures user-data-stream fill: the adapter computes the fee notional (last_qty * last_px), multiplies by the fee rate, then calls Money::from_decimal(amount, currency). Money::from_decimal only accepts decimals representable in the currency's fixed precision and within the i64-backed MoneyRaw range, so it fails when the computed fee has more fractional digits than the currency allows or overflows the raw range. The message includes the offending amount and the underlying conversion error.
Source
Thrown at crates/adapters/binance/src/futures/websocket/streams/parse_exec.rs:197
Money::from_decimal(amount, currency)
.map_err(|e| anyhow::anyhow!("invalid commission='{raw_commission}': {e}"))
} else if let Some(fee) = taker_fee {
let currency = quote_currency.unwrap_or_else(Currency::USDT);
let notional = last_qty
.as_decimal()
.checked_mul(last_px.as_decimal())
.ok_or_else(|| {
anyhow::anyhow!(
"invalid fee notional for last_qty='{last_qty}' and last_px='{last_px}': multiplication overflow",
)
})?;
let amount = fee.checked_mul(notional).ok_or_else(|| {
anyhow::anyhow!(
"invalid fee amount for taker_fee='{fee}' and notional='{notional}': multiplication overflow"
)
})?;
Money::from_decimal(amount, currency)
.map_err(|e| anyhow::anyhow!("invalid fee amount='{amount}': {e}"))
} else {
Ok(Money::zero(Currency::USDT()))
}
}
/// Converts a Binance Futures order update (Trade type) to a Nautilus fill report.
///
/// # Errors
///
/// Returns an error if report construction fails.
#[expect(clippy::too_many_arguments)]
pub fn parse_futures_order_update_to_fill(
msg: &BinanceFuturesOrderUpdateMsg,
account_id: AccountId,
instrument_id: InstrumentId,
price_precision: u8,
size_precision: u8,
taker_fee: Option<Decimal>,View on GitHub (pinned to a4b06ed870)
Solutions
- Compare the logged amount's decimal places with the fee currency's precision from your instrument definitions; the mismatch between them is the direct cause
- Refresh the Binance Futures instrument catalogue (restart the node or force an exchangeInfo reload) so the currency precision matches what the venue reports
- If it recurs, quantize the fee to the currency precision before Money construction (adapter patch, e.g. amount.round_dp(currency.precision as i32)) and report upstream with the raw fill payload
- Track the NautilusTrader repository for fixes to Futures fee parsing and update to the patched version
Example fix
// before
Money::from_decimal(amount, currency)
.map_err(|e| anyhow::anyhow!("invalid fee amount='{amount}': {e}"))
// after: snap the computed fee to the currency's precision first
let amount = amount.round_dp(currency.precision as i32);
Money::from_decimal(amount, currency)
.map_err(|e| anyhow::anyhow!("invalid fee amount='{amount}': {e}")) Defensive patterns
Strategy: try-catch
Try / catch
Catch errors around fill/commission processing per message; match on the 'invalid fee amount' prefix, log the raw fill event and currency precision, and continue consuming the stream rather than tearing down the user-data stream for one unrepresentable fee.
Prevention
- Keep the Binance instrument catalogue fresh so currency precision matches exchangeInfo
- Dry-run high-precision or dust-quantity symbols in paper trading before going live
- Monitor logs for 'invalid fee amount' and retain the raw payload for upstream reports
When it happens
Trigger: Parsing a Futures fill (order update of type Trade) whose commission computation fee_rate * last_qty * last_px produces a decimal that cannot be scaled into the fee currency's precision, or a notional so large the raw fixed-point value overflows MoneyRaw bounds.
Common situations: Very small fill quantities on high-precision/low-price contracts producing dust fees with sub-precision fractions; stale or wrong currency precision in the instruments cache (exchangeInfo not refreshed); extreme notional values combined with high fee rates overflowing the fixed-point range.
Related errors
- Invalid price_match value: {s:?}
- Unsupported underlying type '{underlying_type}' for TRADIFI_
- callbackRate {rate}% out of Binance range [{min_rate}, {max_
- BinanceFuturesDataClient requires UsdM or CoinM product type
- custom data request requires `instrument_id` metadata
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/881581741dbcd531.
Report an issue: GitHub.