nautechsystems/nautilus_trader · error

Continuous future first_pre_instrument_id {instrument_id} wa

Error message

Continuous future first_pre_instrument_id {instrument_id} was not found in transitions

What it means

When building a continuous-future bar request/subscription, an optional `first_pre_instrument_id` chain bound was supplied that does not match the `pre_instrument_id` of any transition row in the parsed transition table. The library validates that every explicit chain boundary actually exists among the transitions so the continuous series cannot be anchored to a nonexistent contract.

Source

Thrown at crates/data/src/engine/requests.rs:407

        LAST_POST_INSTRUMENT_ID,
        primary_bar_type.instrument_id(),
    )?;
    let transitions = parse_transitions(
        primary_bar_type,
        transitions_value,
        adjustment_mode.is_ratio(),
    )?;

    if transitions.is_empty() {
        anyhow::bail!("Continuous future transitions must not be empty");
    }

    if let Some(instrument_id) = first_pre_instrument_id
        && !transitions
            .iter()
            .any(|row| row.pre_instrument_id == instrument_id)
    {
        anyhow::bail!(
            "Continuous future first_pre_instrument_id {instrument_id} was not found in transitions"
        );
    }

    if let Some(instrument_id) = last_post_instrument_id
        && !transitions
            .iter()
            .any(|row| row.post_instrument_id == instrument_id)
    {
        anyhow::bail!(
            "Continuous future last_post_instrument_id {instrument_id} was not found in transitions"
        );
    }

    Ok(ContinuousFutureRequest {
        primary_bar_type,
        request_bar_aggregation: RequestBarAggregation {
            bar_types,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set `first_pre_instrument_id` to exactly the `pre_instrument_id` of the first transition row (verify capitalization and expiry code).
  2. Omit the `first_pre_instrument_id` parameter entirely to let the series start at the first transition.
  3. Regenerate or re-fetch the `transitions` table so it contains the bound you are passing.
  4. Log/inspect the parsed transitions (pre_instrument_id values) and diff against the requested bound.

Example fix

// before
let params = json!({"transitions": rows, "first_pre_instrument_id": "ESZ5"});
// after
let params = json!({"transitions": rows, "first_pre_instrument_id": "ESZ5-CME"}); // exact pre_instrument_id from transitions[0]
Defensive patterns

Strategy: validation

Validate before calling

// Rust, before building request
if let Some(bound) = &params.first_pre_instrument_id {
    assert!(transitions.iter().any(|t| &t.pre_instrument_id == bound),
        "first_pre_instrument_id {bound} not in transitions");
}

Type guard

fn bound_in_transitions(bound: &InstrumentId, transitions: &[Transition]) -> bool {
    transitions.iter().any(|t| t.pre_instrument_id == *bound)
}

Prevention

When it happens

Trigger: Calling continuous_future_request_from_bars or continuous_future_subscription_from_bars with a `first_pre_instrument_id` request parameter whose instrument ID does not equal any row's `pre_instrument_id` in the `transitions` parameter.

Common situations: Typo in the contract symbol passed as the chain start; using the expiry-month root (e.g. ESZ5) instead of the exact pre-transition contract listed in the transitions table; transitions regenerated after a data refresh while the client still passes an old bound; copying a bound from a different continuous series or data source.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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