{"record":{"id":"8d858b80d0e0b65d","repo":"nautechsystems/nautilus_trader","slug":"tick-size-tick-size-is-not-exactly-representable","errorCode":null,"errorMessage":"Tick size {tick_size} is not exactly representable at Polymarket price precision {POLYMARKET_PRICE_PRECISION}","messagePattern":"Tick size (.+?) is not exactly representable at Polymarket price precision (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/http/parse.rs","lineNumber":325,"sourceCode":"        .ts_event(ts_event)\n        .ts_init(ts_init)\n        .build()?;\n\n    Ok(InstrumentAny::BinaryOption(rebuilt))\n}\n\n// Returns the tradeable price bounds `[tick_size, 1 - tick_size]` for a Polymarket outcome,\n// mirroring the venue range enforced in `PolymarketOrderBuilder::validate_limit_price`.\npub(crate) fn tick_relative_price_bounds(tick_size: Decimal) -> anyhow::Result<(Price, Price)> {\n    anyhow::ensure!(\n        tick_size > Decimal::ZERO,\n        \"Tick size {tick_size} must be positive\"\n    );\n\n    let min_price = Price::from_decimal_dp(tick_size, POLYMARKET_PRICE_PRECISION)?;\n    let max_price = Price::from_decimal_dp(Decimal::ONE - tick_size, POLYMARKET_PRICE_PRECISION)?;\n\n    anyhow::ensure!(\n        min_price.as_decimal() == tick_size,\n        \"Tick size {tick_size} is not exactly representable at Polymarket price precision {POLYMARKET_PRICE_PRECISION}\"\n    );\n    Ok((min_price, max_price))\n}\n\nfn build_info_json(def: &PolymarketInstrumentDef) -> serde_json::Value {\n    let mut map = serde_json::Map::new();\n    map.insert(\n        \"token_id\".to_string(),\n        serde_json::Value::String(def.token_id.to_string()),\n    );\n    map.insert(\n        \"condition_id\".to_string(),\n        serde_json::Value::String(def.condition_id.to_string()),\n    );\n    map.insert(\n        \"market_id\".to_string(),","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/http/parse.rs#L307-L343","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet tick_size = parse_decimal_exact(new_tick_size)?;\nlet (min_price, max_price) = tick_relative_price_bounds(tick_size)?;\n// after\nlet tick_size = parse_decimal_exact(new_tick_size)?;\nif tick_size.normalize().scale() > POLYMARKET_PRICE_PRECISION as u32 {\n    anyhow::bail!(\"unsupported tick precision for {new_tick_size}\");\n}\nlet (min_price, max_price) = tick_relative_price_bounds(tick_size)?;","handlingStrategy":"validation","validationCode":"fn tick_representable(tick: Decimal, precision: u8) -> bool {\n    tick.normalize().scale() <= precision as u32\n}","typeGuard":"fn is_supported_tick(tick: Decimal) -> bool {\n    [dec!(0.1), dec!(0.01), dec!(0.001)].contains(&tick.normalize())\n}","tryCatchPattern":"match tick_relative_price_bounds(tick_size) {\n    Ok(bounds) => bounds,\n    Err(e) => { warn!(\"tick not representable: {e}\"); bail!(\"unsupported tick precision\") }\n}","preventionTips":["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."],"tags":["rust","precision","decimal","polymarket"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}