nautechsystems/nautilus_trader · error
{field} {value} must be non-negative
Error message
{field} {value} must be non-negative What it means
validate_quantity_evidence enforces that a quantity-like decimal from provider evidence is usable as a domain Quantity. When allow_zero is set, the value must be >= 0; this error fires for a negative value where zero is permitted (e.g. a cumulative/cancelled quantity).
Source
Thrown at crates/adapters/polymarket/src/execution/reconciliation.rs:274
let instrument_outcome = binary
.outcome
.context("Polymarket instrument is missing outcome metadata")?;
anyhow::ensure!(
instrument_outcome == outcome.as_str(),
"provider outcome {outcome} does not match instrument outcome {instrument_outcome}",
);
Ok(())
}
fn validate_quantity_evidence(
value: Decimal,
precision: u8,
field: &str,
allow_zero: bool,
) -> anyhow::Result<()> {
if allow_zero {
anyhow::ensure!(
value >= Decimal::ZERO,
"{field} {value} must be non-negative"
);
} else {
anyhow::ensure!(value > Decimal::ZERO, "{field} {value} must be positive");
}
let quantity = Quantity::from_decimal_dp(value, precision).with_context(|| {
format!("failed to represent {field} {value} with quantity precision {precision}")
})?;
anyhow::ensure!(
quantity.as_decimal() == value,
"{field} {value} is not exactly representable with quantity precision {precision}",
);
Ok(())
}
fn validate_price_evidence(value: Decimal, precision: u8, field: &str) -> anyhow::Result<()> {View on GitHub (pinned to 18893faf8b)
Solutions
- Log the raw provider field and check whether the endpoint returns signed deltas; convert to absolute values before validation.
- Verify upstream arithmetic is not accidentally negating the value (e.g. size_remaining = size - filled with bad inputs).
- Skip or clamp obviously invalid negative rows only after confirming they represent no-op events.
- Report/provider-side: check for API version changes that introduced signed semantics.
Example fix
// before
validate_quantity_evidence(row.size, precision, "size", true)?;
// after
let size = row.size;
anyhow::ensure!(size >= Decimal::ZERO, "provider size must be non-negative, got {size}");
validate_quantity_evidence(size, precision, "size", true)?; Defensive patterns
Strategy: validation
Validate before calling
fn is_non_negative(v: Decimal) -> bool { v >= Decimal::ZERO } Try / catch
match validate_quantity_evidence(value, precision, field, true) {
Ok(()) => (),
Err(e) if e.to_string().contains("non-negative") => warn!("skipping negative {} for {}", field, trade_id),
Err(e) => return Err(e),
} Prevention
- Convert signed provider deltas to absolute values before quantity validation
- Check sign conventions of any endpoint returning cancellation/decrease amounts
- Assert quantities are non-negative at parse time, not deep in reconciliation
When it happens
Trigger: validate_order_row_values or validate_trade_values passes a negative Decimal for a field validated with allow_zero=true (e.g. negative size, negative filled quantity from the provider).
Common situations: Provider API returning signed amounts for cancellations or decreases; subtracting values upstream and passing a delta instead of an absolute quantity; sign-convention changes in provider payloads.
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
- {field} {value} must be positive
- AX requires whole contract quantities, was {}
- Order quantity must be at least 1 contract
- AX minimum_order_size must be a positive whole number, was {
- AX initial_margin_pct must be positive, was {initial_margin_
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c47b2ae322e8162b.
Report an issue: GitHub.