nautechsystems/nautilus_trader · error
Commission must be greater than or equal to zero
Error message
Commission must be greater than or equal to zero
What it means
PerpetualFeeModel::new (or similar fee model constructor) validates that the commission amount passed in is non-negative. A negative Money value would produce nonsensical (negative) fees, so the constructor rejects it with anyhow::bail. This is a fail-fast guard at model construction time.
Source
Thrown at crates/execution/src/models/fee.rs:266
extends = PyFeeModel,
skip_from_py_object
)
)]
pub struct FixedFeeModel {
commission: Money,
zero_commission: Money,
charge_commission_once: bool,
}
impl FixedFeeModel {
/// Creates a new [`FixedFeeModel`] instance.
///
/// # Errors
///
/// Returns an error if `commission` is negative.
pub fn new(commission: Money, charge_commission_once: Option<bool>) -> anyhow::Result<Self> {
if commission.raw < 0 {
anyhow::bail!("Commission must be greater than or equal to zero")
}
let zero_commission = Money::zero(commission.currency);
Ok(Self {
commission,
zero_commission,
charge_commission_once: charge_commission_once.unwrap_or(true),
})
}
}
impl FeeModel for FixedFeeModel {
fn get_commission(
&self,
order: &OrderAny,
_fill_quantity: Quantity,
_fill_px: Price,
_instrument: &InstrumentAny,
) -> anyhow::Result<Money> {View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the Money value passed as `commission` and correct its sign before constructing the model
- Clamp or validate at the config boundary: reject negative commission inputs when parsing user config
- If the rate is legitimately signed, apply the sign to the notional calculation instead of the commission
Example fix
// before let model = PerpetualFeeModel::new(Money::new(-Decimal::new(15, 1), Currency::USD()), None)?; // after let commission = Money::new(Decimal::new(15, 1), Currency::USD()); assert!(commission.raw >= Decimal::ZERO); let model = PerpetualFeeModel::new(commission, None)?;
Defensive patterns
Strategy: validation
Validate before calling
if commission.raw < Decimal::ZERO {
return Err(anyhow::anyhow!("commission must be >= 0, got {}", commission));
} Type guard
fn is_non_negative(m: &Money) -> bool { m.raw >= Decimal::ZERO } Try / catch
match FeeModel::new(commission, once) {
Ok(model) => model,
Err(e) => { log::error!("fee model init failed: {e}"); return Err(e); }
} Prevention
- Validate fee amounts when loading strategy/venue config
- Use unsigned or validated builders for Money fee inputs
- Add unit tests covering negative-commission construction
When it happens
Trigger: Calling the fee model's `new(commission, charge_commission_once)` with a `Money` whose `raw` decimal is < 0, e.g. `Money::new(-1.5, Currency::USD())` or a commission computed from a negative rate.
Common situations: Loading commission from config where a sign was mistyped, computing commission as a signed delta instead of an absolute value, or a currency conversion/rounding pipeline that flipped the sign.
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
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0dbf884e41c6f87e.
Report an issue: GitHub.