nautechsystems/nautilus_trader · error
Invalid `ContingencyType`
Error message
Invalid `ContingencyType`
What it means
This panic comes from `parse_contingency_type` in the SQL order model when deserializing a persisted contingency type string. The code maps the sentinel value 'NO_CONTINGENCY' to `None` and otherwise delegates to `ContingencyType::from_str`, panicking via `.expect("Invalid `ContingencyType`")` if the string is not a recognized `ContingencyType` variant. It is a data-integrity guard: the database is expected to contain only valid enum values written by this library.
Source
Thrown at crates/infrastructure/src/sql/models/orders.rs:1267
.map(|tags| tags.iter().map(|tag| Ustr::from(tag.as_str())).collect())
}
fn parse_trigger_type(value: Option<&str>) -> Option<TriggerType> {
value.and_then(|value| {
if value.eq_ignore_ascii_case("NO_TRIGGER") {
None
} else {
Some(TriggerType::from_str(value).expect("Invalid `TriggerType`"))
}
})
}
fn parse_contingency_type(value: Option<&str>) -> Option<ContingencyType> {
value.and_then(|value| {
if value.eq_ignore_ascii_case("NO_CONTINGENCY") {
None
} else {
Some(ContingencyType::from_str(value).expect("Invalid `ContingencyType`"))
}
})
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
#[rstest]
#[case(None, None)]
#[case(Some("NO_TRIGGER"), None)]
#[case(Some("LAST_PRICE"), Some(TriggerType::LastPrice))]
fn test_parse_trigger_type_accepts_legacy_absence(
#[case] value: Option<&str>,
#[case] expected: Option<TriggerType>,
) {View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the offending row (`SELECT contingency_type FROM orders WHERE ...`) and correct it to a valid `ContingencyType` value or 'NO_CONTINGENCY'
- List distinct `contingency_type` values and compare against the valid `ContingencyType` variants (e.g. OTO, OCO, OUO)
- Fix the writer that inserted the bad value so it serializes the enum through the library's serializer instead of a hand-built string
- If the value is a valid variant from a newer version, upgrade nautilus so `ContingencyType::from_str` recognizes it
Example fix
// before (bad row value) contingency_type = 'OC0' // after contingency_type = 'OCO'
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_contingency(value: &str) -> bool {
value.eq_ignore_ascii_case("NO_CONTINGENCY") || ContingencyType::from_str(value).is_some()
}
// call before reading/accepting rows: if !is_valid_contingency(s) { reject row } Type guard
fn valid_contingency(s: &str) -> Option<ContingencyType> {
if s.eq_ignore_ascii_case("NO_CONTINGENCY") { None } else { ContingencyType::from_str(s) }
} Prevention
- Only write `ContingencyType` values through the library serializer
- Validate enum strings before inserting rows manually or via ETL
- Keep writer and reader nautilus versions aligned
When it happens
Trigger: Reading an `orders` row whose `contingency_type` column holds a string that is not a valid `ContingencyType` variant (and is not 'NO_CONTINGENCY') — e.g. an empty string, a manually inserted/edited DB value, a typo like 'OC0' instead of 'OCO', or a value written by a newer/older schema version the current code cannot parse.
Common situations: Hand-written SQL migrations or seed data inserting raw contingency strings; rows written by a different nautilus version whose enum spelling changed; ETL scripts copying values from another schema; manual DB fixes.
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 `OrderSide`
- Invalid `PositionSide`
- Execution intent {} has unknown purpose {}
- Invalid scientific notation exponent '{exponent}': must be a
- Invalid NodeState value
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0d2ad2ae0a65b28f.
Report an issue: GitHub.