nautechsystems/nautilus_trader · error · anyhow::Error
invalid Bybit symbol '{value_ref}': expected suffix in {VALI
Error message
invalid Bybit symbol '{value_ref}': expected suffix in {VALID_SUFFIXES:?} What it means
The BybitSymbol newtype validates that raw input carries a valid Bybit product suffix (e.g. -SPOT, -LINEAR, -INVERSE). The input is uppercased, and if after normalization it still has no recognized suffix, construction fails. This prevents malformed instrument IDs from entering the adapter.
Source
Thrown at crates/adapters/bybit/src/common/symbol.rs:52
pub struct BybitSymbol {
value: Ustr,
}
impl BybitSymbol {
/// Creates a new [`BybitSymbol`] after validating the suffix and normalizing to upper case.
///
/// # Errors
///
/// Returns an error if the value does not contain one of the recognized Bybit suffixes.
pub fn new<S: AsRef<str>>(value: S) -> anyhow::Result<Self> {
let value_ref = value.as_ref();
let needs_upper = value_ref.bytes().any(|b| b.is_ascii_lowercase());
let normalized: Cow<'_, str> = if needs_upper {
Cow::Owned(value_ref.to_ascii_uppercase())
} else {
Cow::Borrowed(value_ref)
};
anyhow::ensure!(
has_valid_suffix(normalized.as_ref()),
"invalid Bybit symbol '{value_ref}': expected suffix in {VALID_SUFFIXES:?}"
);
Ok(Self {
value: Ustr::from(normalized.as_ref()),
})
}
/// 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.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Append the correct suffix: e.g. BTCUSDT-LINEAR, ETHUSDT-SPOT, BTCUSDT-INVERSE
- Check VALID_SUFFIXES in crates/adapters/bybit/src/common/symbol.rs for the accepted set
- Convert via the instrument definitions from the Bybit API rather than raw ticker strings
Example fix
// before
let sym = BybitSymbol::new("BTCUSDT")?;
// after
let sym = BybitSymbol::new("BTCUSDT-LINEAR")?; Defensive patterns
Strategy: validation
Validate before calling
fn has_valid_suffix(s: &str) -> bool {
["-SPOT", "-LINEAR", "-INVERSE"].iter().any(|sfx| s.ends_with(sfx))
}
// check before construction:
assert!(has_valid_suffix(&raw.to_ascii_uppercase()), "add a Bybit product suffix"); Try / catch
let symbol = BybitSymbol::new(raw)
.with_context(|| format!("{raw} needs a Bybit suffix like -SPOT/-LINEAR/-INVERSE"))?; Prevention
- Never reuse raw exchange tickers as Nautilus instrument IDs
- Derive symbols from downloaded instrument definitions
- Keep a central mapping from venue ticker to suffixed instrument ID
When it happens
Trigger: Creating BybitSymbol::new("BTCUSDT") or any symbol without a supported suffix such as -SPOT / -LINEAR / -INVERSE.
Common situations: Reusing symbol strings from another exchange adapter (Binance, Bybit raw API) without adding the NautilusTrader product suffix; hardcoding venue-neutral symbols in config.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- invalid 'bbo_level': '{s}', expected 1, 2, 3, 4, or 5
- invalid 'take_profit' price: '{s}', expected a non-negative
- invalid 'stop_loss' price: '{s}', expected a non-negative va
- invalid price for '{key}': '{s}', expected a finite non-nega
- TP override fields require 'take_profit' to be set
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c177a54b673c3ed6.
Report an issue: GitHub.