nautechsystems/nautilus_trader · error
Invalid `BookAction`, was '{invalid}'
Error message
Invalid `BookAction`, was '{invalid}' What it means
`parse_book_action` converts the Databento MBO action character ('A' add, 'C' cancel, 'M' modify, 'R' clear) into a `BookAction` enum. Fill ('F') and None ('N') are deliberately excluded because their book impact arrives as explicit Cancel/Modify events; any other character is invalid and bails.
Source
Thrown at crates/adapters/databento/src/decode/primitives.rs:72
}
}
/// Parses a Databento book action character into a `BookAction` enum.
///
/// # Errors
///
/// Returns an error if `c` is not a valid `BookAction` character.
pub fn parse_book_action(c: c_char) -> anyhow::Result<BookAction> {
match c as u8 as char {
'A' => Ok(BookAction::Add),
'C' => Ok(BookAction::Delete),
'M' => Ok(BookAction::Update),
'R' => Ok(BookAction::Clear),
// 'F' (Fill) and 'N' (None) are deliberately NOT book actions: fills
// are attribution records whose book impact arrives as the explicit
// Cancel/Modify of the same match event (`decode_mbo_msg` filters
// them out before calling this).
invalid => anyhow::bail!("Invalid `BookAction`, was '{invalid}'"),
}
}
/// Parses a Databento option kind character into an `OptionKind` enum.
///
/// # Errors
///
/// Returns an error if `c` is not a valid `OptionKind` character.
pub fn parse_option_kind(c: c_char) -> anyhow::Result<OptionKind> {
match c as u8 as char {
'C' => Ok(OptionKind::Call),
'P' => Ok(OptionKind::Put),
invalid => anyhow::bail!("Invalid `OptionKind`, was '{invalid}'"),
}
}
pub(super) fn parse_currency_or_usd_default(
value: Result<&str, impl std::error::Error>,View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the record's action field against the Databento MBO spec
- Ensure 'F'/'N' records are filtered before parse (decode_mbo_msg does this) — upgrade if your version doesn't
- Upgrade the adapter/dbn crates if Databento introduced new action codes
- Sanitize or drop corrupt records at the stream source
Example fix
// before
MboMsg { action: b'X', ... } // invalid action char
// after
MboMsg { action: b'A', ... } // A/C/M/R only Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_book_action(action: u8) -> bool { matches!(action, b'A' | b'C' | b'M' | b'R') }
// filter 'F' and 'N' before decode, as decode_mbo_msg does Type guard
fn is_book_action(action: u8) -> Option<u8> { matches!(action, b'A'|b'C'|b'M'|b'R').then_some(action) } Try / catch
match decode_record(record) {
Ok(d) => d,
Err(e) if e.to_string().contains("Invalid `BookAction`") => { /* drop corrupt record */ }
Err(e) => return Err(e),
} Prevention
- Validate MBO action chars against {'A','C','M','R'} at ingest
- Filter 'F'/'N' action records before book decoding
- Sanitize replay/test data to use only documented action codes
- Keep dbn/adapter versions current for new action codes
When it happens
Trigger: Decoding an `MboMsg` whose `action` field is a character outside {'A','C','M','R'} (and the deliberately-unsupported 'F'/'N' which decode_mbo_msg should filter out first).
Common situations: Corrupt or truncated records; new Databento action codes added upstream; feeding hand-crafted MBO records in tests or replay with a wrong action char.
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 `OptionKind`, was '{invalid}'
- Invalid `StatusMsg` reason, was '{invalid}'
- Invalid `StatusMsg` trading_event, was '{value}'
- `handle_book_mbo` {IMPL_ERR} `{}`
- Invalid NodeState value
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/47d25d6ef9d502b6.
Report an issue: GitHub.