nautechsystems/nautilus_trader · error
Tick size {tick_size} is not exactly representable at Polyma
Error message
Tick size {tick_size} is not exactly representable at Polymarket price precision {POLYMARKET_PRICE_PRECISION} What it means
After computing min_price = tick_size at POLYMARKET_PRICE_PRECISION, tick_relative_price_bounds verifies the Decimal round-trips exactly. This error is thrown when the tick size has more decimal places than Polymarket's price precision supports, so it cannot be represented exactly.
Source
Thrown at crates/adapters/polymarket/src/http/parse.rs:325
.ts_event(ts_event)
.ts_init(ts_init)
.build()?;
Ok(InstrumentAny::BinaryOption(rebuilt))
}
// Returns the tradeable price bounds `[tick_size, 1 - tick_size]` for a Polymarket outcome,
// mirroring the venue range enforced in `PolymarketOrderBuilder::validate_limit_price`.
pub(crate) fn tick_relative_price_bounds(tick_size: Decimal) -> anyhow::Result<(Price, Price)> {
anyhow::ensure!(
tick_size > Decimal::ZERO,
"Tick size {tick_size} must be positive"
);
let min_price = Price::from_decimal_dp(tick_size, POLYMARKET_PRICE_PRECISION)?;
let max_price = Price::from_decimal_dp(Decimal::ONE - tick_size, POLYMARKET_PRICE_PRECISION)?;
anyhow::ensure!(
min_price.as_decimal() == tick_size,
"Tick size {tick_size} is not exactly representable at Polymarket price precision {POLYMARKET_PRICE_PRECISION}"
);
Ok((min_price, max_price))
}
fn build_info_json(def: &PolymarketInstrumentDef) -> serde_json::Value {
let mut map = serde_json::Map::new();
map.insert(
"token_id".to_string(),
serde_json::Value::String(def.token_id.to_string()),
);
map.insert(
"condition_id".to_string(),
serde_json::Value::String(def.condition_id.to_string()),
);
map.insert(
"market_id".to_string(),View on GitHub (pinned to 18893faf8b)
Solutions
- Use only tick sizes that are exact at POLYMARKET_PRICE_PRECISION (e.g. 0.1, 0.01, 0.001 depending on the constant).
- If the venue added a new tick precision, bump POLYMARKET_PRICE_PRECISION or extend the supported-tick handling and update tests.
- Drop/ignore the instrument update with a warning rather than rebuilding with a rounded price.
Example fix
// before
let tick_size = parse_decimal_exact(new_tick_size)?;
let (min_price, max_price) = tick_relative_price_bounds(tick_size)?;
// after
let tick_size = parse_decimal_exact(new_tick_size)?;
if tick_size.normalize().scale() > POLYMARKET_PRICE_PRECISION as u32 {
anyhow::bail!("unsupported tick precision for {new_tick_size}");
}
let (min_price, max_price) = tick_relative_price_bounds(tick_size)?; Defensive patterns
Strategy: validation
Validate before calling
fn tick_representable(tick: Decimal, precision: u8) -> bool {
tick.normalize().scale() <= precision as u32
} Type guard
fn is_supported_tick(tick: Decimal) -> bool {
[dec!(0.1), dec!(0.01), dec!(0.001)].contains(&tick.normalize())
} Try / catch
match tick_relative_price_bounds(tick_size) {
Ok(bounds) => bounds,
Err(e) => { warn!("tick not representable: {e}"); bail!("unsupported tick precision") }
} Prevention
- Only use tick sizes that are exact multiples of 10^-POLYMARKET_PRICE_PRECISION.
- If Polymarket adds finer ticks, update POLYMARKET_PRICE_PRECISION and the supported-tick tests together.
- Round-check with Decimal comparisons, never floats.
When it happens
Trigger: create_instrument_from_def or rebuild_instrument_with_tick_size receiving a tick size like 0.001 when POLYMARKET_PRICE_PRECISION only allows fewer decimal places (e.g. 0.01/0.001 vs a 2-dp precision), making min_price.as_decimal() != tick_size.
Common situations: Polymarket introducing non-power-of-ten or finer tick sizes than the adapter's fixed precision, or a market message carrying a tick size with excessive precision.
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
- invalid signed E18 integer for {field}: {value}
- AX {field} scale must not exceed 26 for exact percent conver
- Failed to create avg_px price: {e}
- {field} {value} is not exactly representable with quantity p
- historical {field} {value} exceeds the maximum representable
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8d858b80d0e0b65d.
Report an issue: GitHub.