{"record":{"id":"849d884c96a44b01","repo":"nautechsystems/nautilus_trader","slug":"invalid-price-type-was-price-type","errorCode":null,"errorMessage":"Invalid `price_type`, was '{price_type}'","messagePattern":"Invalid `price_type`, was '(.+?)'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/xrate.rs","lineNumber":64,"sourceCode":") -> anyhow::Result<Option<Decimal>> {\n    if from_currency == to_currency {\n        // When the source and target currencies are identical,\n        // no conversion is needed; return an exchange rate of one.\n        return Ok(Some(Decimal::ONE));\n    }\n\n    if quotes_bid.is_empty() || quotes_ask.is_empty() {\n        anyhow::bail!(\"Quote maps must not be empty\");\n    }\n\n    if quotes_bid.len() != quotes_ask.len() {\n        anyhow::bail!(\"Quote maps must have equal lengths\");\n    }\n\n    // Validated here, in the same position as the price-type match this replaced, so the\n    // identical-currency shortcut and the quote-map errors keep their original precedence.\n    if !matches!(price_type, PriceType::Bid | PriceType::Ask | PriceType::Mid) {\n        anyhow::bail!(\"Invalid `price_type`, was '{price_type}'\");\n    }\n\n    // Construct a graph: each currency maps to its neighbors and corresponding conversion rate\n    let mut graph: AHashMap<Ustr, Vec<(Ustr, Decimal)>> = AHashMap::new();\n\n    for (pair, bid) in quotes_bid {\n        let ask = quotes_ask\n            .remove(&pair)\n            .ok_or_else(|| anyhow::anyhow!(\"Missing ask quote for pair {pair}\"))?;\n        let parts: Vec<&str> = pair.split('/').collect();\n\n        if parts.len() != 2 {\n            log::warn!(\"Skipping invalid pair string: {pair}\");\n            continue;\n        }\n\n        if bid <= Decimal::ZERO || ask <= Decimal::ZERO {\n            // Both sides are required to build valid forward and reverse edges.","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/xrate.rs#L46-L82","documentation":"get_exchange_rate only supports Bid, Ask, and Mid price types for computing conversion rates. Any other PriceType value bails with this message. The check was relocated next to the quote-map validation so the identical-currency shortcut keeps its original precedence.","triggerScenarios":"Calling get_exchange_rate (or py_get_exchange_rate) with a PriceType outside Bid/Ask/Mid — e.g. Last or an out-of-enum value from Python bindings.","commonSituations":"Passing PriceType.LAST from Python strategy code that assumes all price types work for FX conversion; an enum value serialized from config that maps to an unsupported variant.","solutions":["Use PriceType::Mid (typical for conversion rates), Bid, or Ask.","For last-trade-based rates, compute the rate from trade ticks instead of the xrate API.","Validate the price_type in Python before calling py_get_exchange_rate."],"exampleFix":"// before\nrate = py_get_exchange_rate(usd, eur, PriceType.LAST, bids, asks)\n// after\nrate = py_get_exchange_rate(usd, eur, PriceType.MID, bids, asks)","handlingStrategy":"validation","validationCode":"ALLOWED = {PriceType.BID, PriceType.ASK, PriceType.MID}\nif price_type not in ALLOWED:\n    raise ValueError(f\"price_type must be BID, ASK or MID, got {price_type}\")","typeGuard":"def is_fx_price_type(pt: PriceType) -> bool:\n    return pt in (PriceType.BID, PriceType.ASK, PriceType.MID)","tryCatchPattern":"try:\n    rate = py_get_exchange_rate(base, quote, price_type, bids, asks)\nexcept Exception as e:\n    if \"Invalid `price_type`\" in str(e):\n        rate = py_get_exchange_rate(base, quote, PriceType.MID, bids, asks)","preventionTips":["Default to PriceType.MID for currency conversion rates.","Never pass trade-derived price types (e.g. LAST) to the xrate API.","Validate enum config values against the supported set at startup."],"tags":["validation","enum","exchange-rate","price-type"],"backgroundTag":"invalid-enum-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}