nautechsystems/nautilus_trader · error · anyhow::Error

Gamma {scope} filter '{key}' must be a decimal number: {e}

Error message

Gamma {scope} filter '{key}' must be a decimal number: {e}

What it means

parse_gamma_filter_decimal parses a Gamma filter as a Decimal via parse_decimal_exact and re-wraps failures as 'Gamma {scope} filter {key} must be a decimal number'. parse_decimal_exact requires exact decimal representation, so scientific notation or extra precision that cannot be represented exactly will fail.

Source

Thrown at crates/adapters/polymarket/src/providers.rs:993

        anyhow::bail!("Gamma {scope} filter '{key}' must be true or false, was '{value}'")
    }
}

fn parse_gamma_filter_u32(scope: &str, key: &str, value: &str) -> anyhow::Result<u32> {
    value.parse::<u32>().map_err(|e| {
        anyhow::anyhow!("Gamma {scope} filter '{key}' must be an unsigned integer: {e}")
    })
}

fn parse_gamma_filter_u64(scope: &str, key: &str, value: &str) -> anyhow::Result<u64> {
    value.parse::<u64>().map_err(|e| {
        anyhow::anyhow!("Gamma {scope} filter '{key}' must be an unsigned integer: {e}")
    })
}

fn parse_gamma_filter_decimal(scope: &str, key: &str, value: &str) -> anyhow::Result<Decimal> {
    parse_decimal_exact(value)
        .map_err(|e| anyhow::anyhow!("Gamma {scope} filter '{key}' must be a decimal number: {e}"))
}

fn parse_gamma_filter_list(scope: &str, key: &str, value: &str) -> anyhow::Result<Vec<String>> {
    let values = value
        .split(',')
        .map(str::trim)
        .map(str::to_string)
        .collect::<Vec<_>>();

    if values.is_empty() || values.iter().any(String::is_empty) {
        anyhow::bail!("Gamma {scope} filter '{key}' must contain non-empty comma-separated values")
    }
    Ok(values)
}

fn parse_gamma_numeric_filter_list(
    scope: &str,
    key: &str,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Write the value as a plain decimal string with a dot separator, e.g. "0.00001" instead of "1e-5"
  2. Convert commas to dots and remove currency symbols/thousands separators before parsing
  3. Round the value to the exchange's supported precision before passing it
  4. Call parse_decimal_exact on the value in your own code first to get the raw reason

Example fix

// before
filters.insert("min_liquidity", "1e5");
// after
filters.insert("min_liquidity", "100000");
Defensive patterns

Strategy: validation

Validate before calling

// Rust: plain decimal check mirroring parse_decimal_exact expectations
fn is_plain_decimal(v: &str) -> bool {
    let v = v.trim();
    !v.is_empty() && !v.contains('e') && !v.contains('E')
        && v.replace('.', "").chars().all(|c| c.is_ascii_digit())
        && v.matches('.').count() <= 1
}

Prevention

When it happens

Trigger: Supplying a price/threshold-style Gamma filter like "1e-5", "0.1.2", "", or a value with too many decimal places that parse_decimal_exact rejects.

Common situations: Scientific-notation numbers from JSON configs, locale decimal commas ("1,25"), or over-precise floats from upstream systems.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/c596a911c949786b. Report an issue: GitHub.