nautechsystems/nautilus_trader · critical
Invalid `OrderSide`
Error message
Invalid `OrderSide`
What it means
Same row-hydration pattern as order_type: the `order_side` column string is parsed with `OrderSide::from_str` and unwrapped with expect(). The panic means the stored side string (expected values like 'BUY'/'SELL') is unrecognized, so the order row cannot be deserialized.
Source
Thrown at crates/infrastructure/src/sql/models/orders.rs:1061
.and_then(|x| x.map(VenueOrderId::from));
let position_id = row
.try_get::<Option<&str>, _>("position_id")
.ok()
.and_then(|x| x.map(PositionId::from));
let account_id = row
.try_get::<Option<&str>, _>("account_id")
.ok()
.and_then(|x| x.map(AccountId::from));
let last_trade_id = row
.try_get::<Option<&str>, _>("last_trade_id")
.ok()
.and_then(|x| x.map(TradeId::from));
let order_type = row
.try_get::<&str, _>("order_type")
.map(|x| OrderType::from_str(x).expect("Invalid `OrderType`"))?;
let order_side = row
.try_get::<&str, _>("order_side")
.map(|x| OrderSide::from_str(x).expect("Invalid `OrderSide`"))?;
let quantity = row.try_get::<&str, _>("quantity").map(Quantity::from)?;
let price = row
.try_get::<Option<&str>, _>("price")
.ok()
.and_then(|x| x.map(Price::from));
let activation_price = row
.try_get::<Option<&str>, _>("activation_price")
.ok()
.and_then(|x| x.map(Price::from));
let trigger_price = row
.try_get::<Option<&str>, _>("trigger_price")
.ok()
.and_then(|x| x.map(Price::from));
let trigger_type = row
.try_get::<Option<&str>, _>("trigger_type")
.ok()
.and_then(parse_trigger_type);
let limit_offset = rowView on GitHub (pinned to 18893faf8b)
Solutions
- Find and fix bad rows: `SELECT id, order_side FROM orders WHERE order_side NOT IN ('BUY','SELL')`
- Normalize the writer to persist canonical 'BUY'/'SELL' strings
- If case is the only problem, normalize with UPPER() in a data migration
- Propagate a parse error instead of expect when handling untrusted data
Example fix
// before
OrderSide::from_str(x).expect("Invalid `OrderSide`")
// after
OrderSide::from_str(&x.to_uppercase()).map_err(|_| ModelError::Parse(format!("bad order_side '{x}'")))? Defensive patterns
Strategy: type-guard
Validate before calling
assert!(matches!(order_side_str, "BUY" | "SELL"), "bad order_side: {order_side_str}"); Type guard
fn is_known_order_side(s: &str) -> bool {
OrderSide::from_str(s).is_ok()
} Try / catch
let order_side = OrderSide::from_str(x)
.map_err(|e| ModelError::Parse(format!("row {}: invalid order_side '{x}': {e}", row_id)))?; Prevention
- Normalize side strings (trim/uppercase) before persisting
- Add a DB CHECK constraint order_side IN ('BUY','SELL')
- Avoid sharing order tables with non-nautilus writers
- Test round-trip persistence of every OrderSide variant
When it happens
Trigger: Calling `OrderModel::from_row` where `order_side` holds values like 'buy' (wrong case), 'B'/'S', a localized string, or data from a foreign schema.
Common situations: Tables shared with non-nautilus writers; case-sensitivity mismatches after manual data loads; adapters persisting their own side naming.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid `OrderType`
- Invalid `TimeInForce`
- Invalid `LiquiditySide`
- Invalid `OrderStatus`
- Invalid `TriggerType`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8469eaa76ef5c712.
Report an issue: GitHub.