nautechsystems/nautilus_trader · error

failed to parse any of {input_len} Lighter instruments: {}

Error message

failed to parse any of {input_len} Lighter instruments: {}

What it means

Raised by parse_order_book_details_instruments_with_status when the venue returned a non-empty set of order-book details (perps + spots) but zero of them could be parsed into instruments. The bail includes the total input count and the first parse error encountered, since every record failed and the first error is the most representative root cause.

Source

Thrown at crates/adapters/lighter/src/http/parse.rs:133

        }
    }

    for detail in spot_details {
        match parse_spot_instrument(registry, detail, ts_init) {
            Ok(instrument) => instruments.push((instrument, detail.order_book.status)),
            Err(e) => {
                log::warn!(
                    "Skipping invalid Lighter spot instrument `{}`: {e}",
                    detail.order_book.symbol,
                );
                first_error.get_or_insert_with(|| e.to_string());
            }
        }
    }

    let input_len = perp_details.len() + spot_details.len();
    if input_len > 0 && instruments.is_empty() {
        anyhow::bail!(
            "failed to parse any of {input_len} Lighter instruments: {}",
            first_error.as_deref().unwrap_or("unknown parse error"),
        );
    }

    Ok(instruments)
}

/// Parses a Lighter trade into a Nautilus [`TradeTick`].
///
/// # Errors
///
/// Returns an error if the price, size, timestamp, or trade id is invalid.
pub fn parse_trade_tick(
    trade: &LighterTrade,
    instrument: &InstrumentAny,
    ts_init: UnixNanos,
) -> anyhow::Result<TradeTick> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the embedded first_error to see why records failed to parse
  2. Update the adapter/parser to match the current Lighter order-book-details API schema
  3. Pin or verify the adapter version against the deployed venue API version
  4. Log a sample raw response to diff against the parser's expectations

Example fix

// before: parse and assume success
let instruments = parse_order_book_details_instruments(&response)?;
// after: fail loudly with a raw sample for diagnosis
let instruments = match parse_order_book_details_instruments(&response) {
    Ok(i) if !i.is_empty() => i,
    Ok(_) | Err(e) => {
        log::error!("Lighter instruments parse failed: {e}; sample={:?}", response.first());
        return Err(e);
    }
};
Defensive patterns

Strategy: try-catch

Validate before calling

// detect an empty/unexpected venue payload before parsing
if perp_details.is_empty() && spot_details.is_empty() {
    return Err("venue returned no order-book details".into());
}

Try / catch

match parse_order_book_details_instruments(&response) {
    Err(e) => {
        let msg = e.to_string();
        if msg.contains("failed to parse any of") {
            log::error!("Lighter schema drift suspected: {msg}; raw={:?}", response.first());
        }
        Err(e)
    }
    ok => ok,
}

Prevention

When it happens

Trigger: Calling get_order_book_details, request_instruments_with_status_for_query, or parse_order_book_details_instruments against a venue response whose records all fail parsing — e.g. an unexpected schema from an API change, new market type the parser does not handle, or corrupt/empty per-record fields.

Common situations: Lighter API schema changes (new fields/renames) breaking the parser, a venue response shape change after an adapter upgrade, or spot/perp detail records in an unexpected format.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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