{"record":{"id":"d33a476a85af7968","repo":"nautechsystems/nautilus_trader","slug":"invalid-orderside-d33a47","errorCode":null,"errorMessage":"Invalid `OrderSide`","messagePattern":"Invalid `OrderSide`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/infrastructure/src/sql/models/positions.rs","lineNumber":53,"sourceCode":"        let trader_id = row.try_get::<&str, _>(\"trader_id\").map(TraderId::from)?;\n        let strategy_id = row\n            .try_get::<&str, _>(\"strategy_id\")\n            .map(StrategyId::from)?;\n        let instrument_id = row\n            .try_get::<&str, _>(\"instrument_id\")\n            .map(InstrumentId::from)?;\n        let account_id = row.try_get::<&str, _>(\"account_id\").map(AccountId::from)?;\n        let opening_order_id = row\n            .try_get::<&str, _>(\"opening_order_id\")\n            .map(ClientOrderId::from)?;\n        let closing_order_id = row\n            .try_get::<Option<&str>, _>(\"closing_order_id\")\n            .ok()\n            .and_then(|x| x.map(ClientOrderId::from));\n        let entry = row\n            .try_get::<&str, _>(\"entry\")\n            .map(OrderSide::from_str)?\n            .expect(\"Invalid `OrderSide`\");\n        let side = row\n            .try_get::<&str, _>(\"side\")\n            .map(PositionSide::from_str)?\n            .expect(\"Invalid `PositionSide`\");\n        let signed_qty = row.try_get::<f64, _>(\"signed_qty\")?;\n        let quantity = row.try_get::<&str, _>(\"quantity\").map(Quantity::from)?;\n        let peak_qty = row.try_get::<&str, _>(\"peak_qty\").map(Quantity::from)?;\n        let quote_currency = row\n            .try_get::<&str, _>(\"quote_currency\")\n            .map(Currency::from)?;\n        let base_currency = row\n            .try_get::<Option<&str>, _>(\"base_currency\")\n            .ok()\n            .and_then(|x| x.map(Currency::from));\n        let settlement_currency = row\n            .try_get::<&str, _>(\"settlement_currency\")\n            .map(Currency::from)?;\n        let avg_px_open = row.try_get::<f64, _>(\"avg_px_open\")?;","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/infrastructure/src/sql/models/positions.rs#L35-L71","documentation":"`AccountPosition::from_row` in positions.rs parses the `entry` column as an `OrderSide` via `OrderSide::from_str` and unwraps it with `.expect(\"Invalid `OrderSide`\")`. If the stored string is not a valid `OrderSide` ('BUY'/'SELL'), the parse returns `None` and row deserialization panics. The library assumes positions rows were written only through its own serialization.","triggerScenarios":"Reading a `positions` row whose `entry` column is not exactly a valid `OrderSide` string (e.g. empty, 'buy' in unexpected casing, 'LONG', or numeric exchange side codes like '1'/'B'), typically from manual inserts or a version/schema mismatch.","commonSituations":"Manual DB edits or ETL scripts writing position rows; restoring rows from a different nautilus schema version; adapters persisting raw venue side strings instead of the nautilus enum text; typos in seed data.","solutions":["Check the failing row's `entry` value in Postgres and rewrite it as a valid `OrderSide` ('BUY' or 'SELL')","Audit all writers of the positions table to ensure they serialize `OrderSide` via the library's `to_string`","Run `SELECT DISTINCT entry FROM positions` and validate every distinct value against `OrderSide::from_str`","Rebuild corrupt rows from the underlying order/fill events rather than ad-hoc string edits"],"exampleFix":"// before\nentry = 'buy'\n// after\nentry = 'BUY'","handlingStrategy":"validation","validationCode":"fn valid_order_side(s: &str) -> bool { OrderSide::from_str(s).is_some() }\n// check before persisting or accepting positions rows","typeGuard":"fn parse_order_side(s: &str) -> Option<OrderSide> { OrderSide::from_str(s) }","tryCatchPattern":null,"preventionTips":["Serialize `OrderSide` with the library `to_string`, never hand-built strings","Run `SELECT DISTINCT entry FROM positions` checks after migrations/imports","Keep the positions table writer and reader on the same schema version"],"tags":["database","parsing","panic","enum"],"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"}