nautechsystems/nautilus_trader · error

Invalid underlying '{}' for {}: expected format 'BASE-QUOTE'

Error message

Invalid underlying '{}' for {}: expected format 'BASE-QUOTE'

What it means

parse_swap_instrument splits the OKX `uly` (underlying) string on '-' to derive base and quote currencies, expecting the 'BASE-QUOTE' format. If the split yields no dash-separated pair, the library throws this error. `validate_underlying` has already rejected an empty underlying, so this fires only when a non-empty uly lacks the expected structure.

Source

Thrown at crates/adapters/okx/src/common/parse.rs:2148

///
/// Returns an error if the instrument definition cannot be parsed.
///
/// # Panics
///
/// Panics if the constructed instrument fails validation.
pub fn parse_swap_instrument(
    definition: &OKXInstrument,
    margin_init: Option<Decimal>,
    margin_maint: Option<Decimal>,
    maker_fee: Option<Decimal>,
    taker_fee: Option<Decimal>,
    ts_init: UnixNanos,
) -> anyhow::Result<InstrumentAny> {
    validate_underlying(definition.inst_id, definition.uly)?;

    let context = format!("SWAP instrument {}", definition.inst_id);
    let (base_currency, quote_currency) = definition.uly.split_once('-').ok_or_else(|| {
        anyhow::anyhow!(
            "Invalid underlying '{}' for {}: expected format 'BASE-QUOTE'",
            definition.uly,
            definition.inst_id
        )
    })?;

    let instrument_id = parse_instrument_id(definition.inst_id);
    let raw_symbol = Symbol::from_ustr_unchecked(definition.inst_id);
    let base_currency = Currency::get_or_create_crypto_with_context(base_currency, Some(&context));
    let quote_currency =
        Currency::get_or_create_crypto_with_context(quote_currency, Some(&context));
    let settlement_currency =
        Currency::get_or_create_crypto_with_context(definition.settle_ccy, Some(&context));
    let is_inverse = match definition.ct_type {
        OKXContractType::Linear => false,
        OKXContractType::Inverse => true,
        OKXContractType::None => {
            anyhow::bail!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Print definition.uly for the failing inst_id and check it contains exactly a 'BASE-QUOTE' pair like "BTC-USD".
  2. Fix the source data so uly matches OKX's 'BTC-USD-TIMING' underlying format (the parser splits on the first '-').
  3. Confirm validate_underlying passed; if uly should be empty, fix the instrument definition instead.
  4. If a new OKX format is genuinely in play, update the parser's split logic upstream.

Example fix

// before
"uly": "BTCUSD"
// after
"uly": "BTC-USD"
Defensive patterns

Strategy: validation

Validate before calling

fn has_base_quote_uly(uly: &str) -> bool {
    !uly.trim().is_empty() && uly.contains('-') && uly.split('-').next().map_or(false, |b| !b.is_empty())
}
// guard: assert!(has_base_quote_uly(&definition.uly), "bad uly: {}", definition.uly);

Type guard

fn parse_uly_pair(uly: &str) -> Option<(&str, &str)> {
    uly.split_once('-')
}

Try / catch

match parse_instrument_any(&definition, ts_init) {
    Ok(inst) => inst,
    Err(e) if e.to_string().contains("expected format 'BASE-QUOTE'") => {
        tracing::warn!(inst_id = %definition.inst_id, "skipping SWAP with malformed uly '{}': {e}", definition.uly);
        continue;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling parse_instrument_any -> parse_swap_instrument with a definition whose uly is non-empty but does not contain a '-' (e.g. "BTCUSD" instead of "BTC-USD", or a single-token underlying).

Common situations: Fixture data written without the exchange's BASE-QUOTE convention; a new OKX instrument family whose underlying uses a different separator; manually constructed definitions in tests or custom adapters feeding the parser.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/4cfff323b805104f. Report an issue: GitHub.