nautechsystems/nautilus_trader · error

Continuous future chain discontinuity for {target_bar_type}:

Error message

Continuous future chain discontinuity for {target_bar_type}: previous post {previous} != current pre {pre_instrument_id}

What it means

The transition chain must be continuous: each row's pre_instrument_id must equal the previous row's post_instrument_id. A gap or jump between consecutive rolls breaks the stitched continuous series and is rejected.

Source

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

        }
        previous_transition_time_ns = Some(transition_time_ns);

        let pre_instrument_id =
            parse_transition_instrument_id(row.get("pre_instrument_id"), target_bar_type)?;
        let post_instrument_id =
            parse_transition_instrument_id(row.get("post_instrument_id"), target_bar_type)?;
        if pre_instrument_id.venue != target_venue || post_instrument_id.venue != target_venue {
            anyhow::bail!(
                "Continuous future segment venue mismatch for {target_bar_type}: target venue {target_venue}, segment venues pre={}, post={}",
                pre_instrument_id.venue,
                post_instrument_id.venue,
            );
        }

        if let Some(previous) = previous_post_instrument_id
            && pre_instrument_id != previous
        {
            anyhow::bail!(
                "Continuous future chain discontinuity for {target_bar_type}: previous post {previous} != current pre {pre_instrument_id}",
            );
        }
        previous_post_instrument_id = Some(post_instrument_id);

        let pre_price = parse_transition_price(row.get("pre_price"), row_value, "pre_price")?;
        let post_price = parse_transition_price(row.get("post_price"), row_value, "post_price")?;
        if is_ratio && (pre_price <= Decimal::ZERO || post_price <= Decimal::ZERO) {
            anyhow::bail!(
                "Continuous future ratio adjustment requires positive prices, was {row_value}"
            );
        }

        transitions.push(ContinuousFutureTransition {
            transition_time_ns,
            pre_instrument_id,
            post_instrument_id,
            pre_price,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Insert the missing transition row so each post connects to the next pre.
  2. Re-sort rows by transition_time_ns after correcting any wrong timestamps, then re-verify the chain.
  3. Programmatically assert transitions[i].pre == transitions[i-1].post before sending.

Example fix

// before
rows = [ ...ESZ5->ESH6, ESM6->ESU6 ] // missing ESH6->ESM6
// after
rows = [ ...ESZ5->ESH6, ESH6->ESM6, ESM6->ESU6 ]
Defensive patterns

Strategy: validation

Validate before calling

for w in transitions.windows(2) {
    assert_eq!(w[1].pre_instrument_id, w[0].post_instrument_id, "chain discontinuity");
}

Prevention

When it happens

Trigger: parse_transitions finds a row whose pre_instrument_id differs from the previous row's post_instrument_id — a missing intermediate roll, duplicated roll skipping a contract, or rows out of order after fixing timestamps.

Common situations: Deleting a roll row by accident; concatenating quarterly roll tables with a gap; sorting rows by time but one roll timestamp is wrong so the chain no longer lines up.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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