nautechsystems/nautilus_trader · error · anyhow::Error
Invalid Hyperliquid symbol format: {symbol}
Error message
Invalid Hyperliquid symbol format: {symbol} What it means
InstrumentId/symbol parsing for Hyperliquid classifies a symbol as perp, spot, or outcome by suffix (e.g. -SPOT or outcome encodings). A symbol matching none of the recognized forms bails with this error.
Source
Thrown at crates/adapters/hyperliquid/src/common/enums.rs:1046
/// Extract product type from an instrument symbol.
///
/// Accepts both Nautilus instrument symbols (`{BASE}-USD-PERP`,
/// `{BASE}-{QUOTE}-SPOT`, `{N}-{YES|NO}-OUTCOME`) and venue wire coin
/// names (`#<encoding>` / `+<encoding>` for HIP-4 outcomes). Callers in
/// the adapter pass both forms.
///
/// # Errors
///
/// Returns error if symbol doesn't match any expected format.
pub fn from_symbol(symbol: &str) -> anyhow::Result<Self> {
if symbol.ends_with("-PERP") {
Ok(Self::Perp)
} else if symbol.ends_with("-SPOT") {
Ok(Self::Spot)
} else if symbol.ends_with(OUTCOME_SYMBOL_SUFFIX) || is_outcome_wire_symbol(symbol) {
Ok(Self::Outcome)
} else {
anyhow::bail!("Invalid Hyperliquid symbol format: {symbol}")
}
}
}
// Outcomes use the `#<encoding>` spot-coin form or the `+<encoding>` token
// form, where the encoding is `10 * outcome + side` and must parse as `u32`.
fn is_outcome_wire_symbol(symbol: &str) -> bool {
let Some(rest) = symbol
.strip_prefix('#')
.or_else(|| symbol.strip_prefix('+'))
else {
return false;
};
!rest.is_empty() && rest.parse::<u32>().is_ok()
}
/// Hyperliquid API environment.
#[derive(View on GitHub (pinned to 18893faf8b)
Solutions
- Format the symbol per Hyperliquid conventions (perp form, spot form with -SPOT suffix, or #/+ outcome encoding).
- Pre-validate the symbol suffix in your ingest/config layer before calling from_symbol.
- Convert external symbols explicitly (e.g. BTCUSDT -> BTC or BTC-SPOT) rather than passing them through.
Example fix
// before
let asset = HyperliquidAssetType::from_symbol("BTCUSDT")?;
// after
let asset = HyperliquidAssetType::from_symbol("BTC")?; // perp
// or HyperliquidAssetType::from_symbol("BTC-SPOT")?; Defensive patterns
Strategy: validation
Validate before calling
fn looks_like_hl_symbol(s: &str) -> bool {
s.ends_with("-SPOT") || s.starts_with('#') || s.starts_with('+') || !s.contains("USDT")
} Try / catch
match HyperliquidAssetType::from_symbol(sym) {
Ok(a) => use_asset(a),
Err(e) => { log::error!("{e}"); /* convert symbol format and retry */ }
} Prevention
- Normalize external symbols (e.g. BTCUSDT -> BTC / BTC-SPOT) before adapter calls.
- Keep a symbol formatter per source exchange.
- Reject unparseable symbols at ingest with a clear message.
When it happens
Trigger: Calling from_symbol with a symbol lacking a recognized suffix, e.g. plain "BTC" without the expected perp/spot/outcome form, or a malformed instrument ID string.
Common situations: Passing Binance-style symbols (BTCUSDT) into the Hyperliquid adapter; missing the @/spot or -SPOT suffix; using outcome tokens without the # or + prefix.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid Hyperliquid bar interval: {s}
- Invalid Hyperliquid outcome symbol '{symbol}': encoding must
- Failed to create quantity from filled_sz: {e}
- Failed to create price from limit_px: {e}
- Failed to create trigger price: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d5aa476e542c7824.
Report an issue: GitHub.