{"record":{"id":"24cb415dcab8ef30","repo":"nautechsystems/nautilus_trader","slug":"invalid-liquidityside","errorCode":null,"errorMessage":"Invalid `LiquiditySide`","messagePattern":"Invalid `LiquiditySide`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/infrastructure/src/sql/models/orders.rs","lineNumber":1103,"sourceCode":"            .ok()\n            .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));\n        let trailing_offset_type = row\n            .try_get::<Option<TrailingOffsetTypePg>, _>(\"trailing_offset_type\")\n            .ok()\n            .flatten()\n            .and_then(|value| value.0);\n        let time_in_force = row\n            .try_get::<&str, _>(\"time_in_force\")\n            .map(|x| TimeInForce::from_str(x).expect(\"Invalid `TimeInForce`\"))?;\n        let expire_time = row\n            .try_get::<Option<&str>, _>(\"expire_time\")\n            .ok()\n            .and_then(|x| x.map(UnixNanos::from));\n        let filled_qty = row.try_get::<&str, _>(\"filled_qty\").map(Quantity::from)?;\n        let liquidity_side = row\n            .try_get::<Option<&str>, _>(\"liquidity_side\")\n            .ok()\n            .and_then(|x| x.map(|x| LiquiditySide::from_str(x).expect(\"Invalid `LiquiditySide`\")));\n        let avg_px = row.try_get::<Option<Decimal>, _>(\"avg_px\").ok().flatten();\n        let slippage = row.try_get::<Option<Decimal>, _>(\"slippage\").ok().flatten();\n        let commissions = row\n            .try_get::<Option<Vec<String>>, _>(\"commissions\")?\n            .map_or_else(Vec::new, |c| {\n                c.into_iter().map(|s| Money::from(&s)).collect()\n            });\n        let status = row\n            .try_get::<&str, _>(\"status\")\n            .map(|x| OrderStatus::from_str(x).expect(\"Invalid `OrderStatus`\"))?;\n        let is_post_only = row.try_get::<bool, _>(\"is_post_only\")?;\n        let is_reduce_only = row.try_get::<bool, _>(\"is_reduce_only\")?;\n        let is_quote_quantity = row.try_get::<bool, _>(\"is_quote_quantity\")?;\n        let display_qty = row\n            .try_get::<Option<&str>, _>(\"display_qty\")\n            .ok()\n            .and_then(|x| x.map(Quantity::from));\n        let emulation_trigger = row","sourceCodeStart":1085,"sourceCodeEnd":1121,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/infrastructure/src/sql/models/orders.rs#L1085-L1121","documentation":"While hydrating the optional `liquidity_side` column, `LiquiditySide::from_str` result is unwrapped with expect(). The panic means a non-NULL liquidity_side value in the row (expected 'MAKER'/'TAKER'/'NONE') is not a valid LiquiditySide, so the order row fails to load.","triggerScenarios":"Calling `OrderModel::from_row` on a row whose `liquidity_side` contains an unrecognized string (wrong case like 'maker' if the parser is case-sensitive, abbreviations 'M'/'T', or values from another system).","commonSituations":"Data imported from exchange reports or third-party databases using different liquidity naming; mixed-version writers; manual updates.","solutions":["Audit the column: `SELECT DISTINCT liquidity_side FROM orders WHERE liquidity_side IS NOT NULL` and fix offending values","Persist canonical LiquiditySide strings from the writer path","Normalize values (trim/upper) in a migration if that is the only mismatch","Map the parse failure into an error instead of expect when reading external data"],"exampleFix":"// before\nx.map(|x| LiquiditySide::from_str(x).expect(\"Invalid `LiquiditySide`\"))\n// after\nx.map(|x| LiquiditySide::from_str(x).map_err(|e| ModelError::Parse(format!(\"invalid liquidity_side '{x}': {e}\")))).transpose()?","handlingStrategy":"type-guard","validationCode":"fn valid_liquidity_side(s: Option<&str>) -> bool {\n    s.map(|s| LiquiditySide::from_str(s).is_ok()).unwrap_or(true)\n}","typeGuard":"fn is_known_liquidity_side(s: &str) -> bool {\n    LiquiditySide::from_str(s).is_ok()\n}","tryCatchPattern":"let liquidity_side = x\n    .map(|x| LiquiditySide::from_str(x)\n        .map_err(|e| ModelError::Parse(format!(\"row {}: invalid liquidity_side '{x}': {e}\", row_id))))\n    .transpose()?;","preventionTips":["Write None rather than 'UNKNOWN' for absent liquidity sides","Normalize case before persisting","Add a CHECK constraint on liquidity_side","Validate exchange fill reports map to MAKER/TAKER before insert"],"tags":["rust","sql","postgres","enum","panic"],"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"}