nautechsystems/nautilus_trader · error
symbol checked for suffix during construction
Error message
symbol checked for suffix during construction
What it means
BybitSymbol::product_type derives the product type from the symbol suffix (-SPOT, -LINEAR, -INVERSE, -OPTION). BybitSymbol::new validates the suffix at construction, so from_suffix is guaranteed to succeed here; the expect encodes that guarantee. A panic means a BybitSymbol was built without going through new (e.g. via unsafe/struct literal or a constructor change).
Source
Thrown at crates/adapters/bybit/src/common/symbol.rs:77
}
/// Returns the underlying symbol without the Bybit suffix.
#[must_use]
pub fn raw_symbol(&self) -> &str {
self.value
.rsplit_once('-')
.map_or(self.value.as_str(), |(prefix, _)| prefix)
}
/// Returns the product type identified by the suffix.
///
/// # Panics
///
/// Panics if the symbol has no valid suffix (unreachable after construction).
#[must_use]
pub fn product_type(&self) -> BybitProductType {
BybitProductType::from_suffix(self.value.as_str())
.expect("symbol checked for suffix during construction")
}
/// Returns the instrument identifier corresponding to this symbol.
#[must_use]
pub fn to_instrument_id(&self) -> InstrumentId {
InstrumentId::new(Symbol::from_ustr_unchecked(self.value), *BYBIT_VENUE)
}
/// Returns the symbol value as `Ustr`.
#[must_use]
pub fn as_ustr(&self) -> Ustr {
self.value
}
}
impl Display for BybitSymbol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.value.as_str())View on GitHub (pinned to 18893faf8b)
Solutions
- Always construct BybitSymbol via BybitSymbol::new (or serde using new)
- Keep VALID_SUFFIXES and BybitProductType::from_suffix in sync when adding product types
- Add a unit test asserting product_type() for every valid suffix
- Validate user symbols with BybitSymbol::new and surface the error instead of bypassing it
Example fix
// before
let sym = BybitSymbol { value: Ustr::from("BTCUSDT") }; // bypasses validation
let pt = sym.product_type(); // panics
// after
let sym = BybitSymbol::new("BTCUSDT-SPOT")?;
let pt = sym.product_type(); // BybitProductType::Spot Defensive patterns
Strategy: validation
Validate before calling
let sym = BybitSymbol::new(user_input)?; // validates suffix up front let product_type = sym.product_type(); // safe now
Type guard
fn has_valid_bybit_suffix(value: &str) -> bool {
["-SPOT", "-LINEAR", "-INVERSE", "-OPTION"]
.iter()
.any(|s| value.to_uppercase().contains(s))
} Try / catch
match BybitSymbol::new(raw) {
Ok(sym) => use(sym),
Err(e) => eprintln!("invalid Bybit symbol: {e}"),
} Prevention
- Always construct BybitSymbol via new, never by struct literal
- Keep suffix lists and BybitProductType::from_suffix in sync
- Normalize user symbols to uppercase before validation
When it happens
Trigger: Calling product_type() on a BybitSymbol constructed by bypassing BybitSymbol::new, or after changing VALID_SUFFIXES so it disagrees with BybitProductType::from_suffix's accepted suffixes.
Common situations: Maintainer adds a new suffix to one list but not the other; test code building BybitSymbol directly; deserialization path constructing the struct without validation.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- validated above
- Close command should not be drained
- Flush command should not be drained
- Order invariant violated: first event must be OrderInitializ
- invalid option symbol '{symbol}'
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/52c31afefc336a71.
Report an issue: GitHub.