nautechsystems/nautilus_trader · error · anyhow::Error
Invalid Hyperliquid outcome symbol '{symbol}': encoding must
Error message
Invalid Hyperliquid outcome symbol '{symbol}': encoding must be numeric What it means
parse_outcome_symbol_encoding validates the encoding portion of a Hyperliquid outcome symbol (a prediction-market instrument like 'BTC-up-or-down-...' with a numeric encoding). The library throws this because outcome symbol encodings must be plain ASCII digits parseable as u32; a non-numeric encoding cannot be mapped to Hyperliquid's internal outcome index.
Source
Thrown at crates/adapters/hyperliquid/src/common/parse.rs:284
})
}
fn parse_outcome_symbol_encoding(symbol: &str) -> anyhow::Result<u32> {
let encoding = symbol
.strip_prefix('#')
.or_else(|| symbol.strip_prefix('+'))
.with_context(|| {
format!(
"Invalid Hyperliquid outcome symbol '{symbol}': expected #<encoding> or +<encoding>"
)
})?;
if encoding.is_empty() {
anyhow::bail!("Invalid Hyperliquid outcome symbol '{symbol}': encoding must not be empty");
}
if !encoding.bytes().all(|b| b.is_ascii_digit()) {
anyhow::bail!("Invalid Hyperliquid outcome symbol '{symbol}': encoding must be numeric");
}
encoding
.parse::<u32>()
.with_context(|| format!("Invalid Hyperliquid outcome symbol '{symbol}'"))
}
/// Suffix shared by every Nautilus outcome symbol, mirroring `-PERP` / `-SPOT`.
pub const OUTCOME_SYMBOL_SUFFIX: &str = "-OUTCOME";
/// Yes-side label on Nautilus outcome symbols.
pub const OUTCOME_SIDE_YES: &str = "YES";
/// No-side label on Nautilus outcome symbols.
pub const OUTCOME_SIDE_NO: &str = "NO";
/// Parses a Nautilus outcome instrument symbol of the form
/// `{outcome_index}-{YES|NO}-OUTCOME` into `(outcome_index, side)` where side
/// is `0` for Yes and `1` for No.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the symbol string and fix the encoding segment so it contains only digits 0-9 (e.g. '...-42').
- Obtain outcome symbols from the adapter's parsed instrument definitions rather than constructing them manually.
- Log the raw symbol at parse time and compare against the venue's outcome metadata to find the malformed segment.
- If the venue changed its outcome symbol scheme, refresh instruments and update stored symbol references.
Example fix
// before let symbol = "BTC-up-or-down-1700000000-ab"; // non-numeric encoding let outcome = parse_outcome_symbol(symbol)?; // after let symbol = "BTC-up-or-down-1700000000-3"; // numeric encoding segment let outcome = parse_outcome_symbol(symbol)?;
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_outcome_encoding(encoding: &str) -> bool {
!encoding.is_empty() && encoding.bytes().all(|b| b.is_ascii_digit()) && encoding.parse::<u32>().is_ok()
}
// call before parse_outcome_symbol
if !is_valid_outcome_encoding(&encoding) { /* fix symbol or skip */ } Type guard
fn valid_outcome_symbol(symbol: &str) -> Option<&str> {
let enc = symbol.rsplit('-').next()?;
(!enc.is_empty() && enc.bytes().all(|b| b.is_ascii_digit())).then_some(symbol)
} Prevention
- Source outcome symbols from the adapter's parsed instruments, not hand-built strings
- Validate symbol segments contain only digits before use
- Log raw symbols when parsing fails to catch format drift early
When it happens
Trigger: Calling parse_outcome_symbol (directly or via instrument/symbol parsing when subscribing or requesting data for a Hyperliquid outcome market) with a symbol whose encoding segment contains letters, dashes, spaces, or any non-digit character, e.g. '...-12x' or an empty/malformed segment that passed the earlier empty check.
Common situations: Hand-constructed outcome symbol strings, symbols copied from a different exchange's format, stale cached instrument IDs after a venue listing change, or programmatic symbol building that interpolates a non-numeric suffix.
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
- Unsupported order type for Hyperliquid: {order.order_type():
- Not a subscription channel: {kind}
- Unsupported OrderType for conditional orders: {value:?}
- {e}
- {FAILED}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/098eef5004b1136b.
Report an issue: GitHub.