nautechsystems/nautilus_trader · error
Continuous future transitions must not be empty
Error message
Continuous future transitions must not be empty
What it means
A continuous future request must contain at least one contract transition row (the chain of contract rolls). An empty transitions list would produce a continuous series with no segments, which is meaningless, so parse_continuous_future bails with this error.
Source
Thrown at crates/data/src/engine/requests.rs:399
})?;
let first_pre_instrument_id = parse_optional_chain_bound(
params,
FIRST_PRE_INSTRUMENT_ID,
primary_bar_type.instrument_id(),
)?;
let last_post_instrument_id = parse_optional_chain_bound(
params,
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!(View on GitHub (pinned to 18893faf8b)
Solutions
- Supply at least one transition row (pre/post instrument IDs with roll dates) in continuous_future_transitions.
- Check that the source of the contract chain actually returned contracts before constructing the request.
- Validate transitions.len() > 0 in the caller before invoking the subscription/request API.
Example fix
// before
let params = params_with(CONTINUOUS_FUTURE_TRANSITIONS, json!([]));
// after
let params = params_with(CONTINUOUS_FUTURE_TRANSITIONS, json!([
{"pre_instrument_id": "ESZ5.XCME", "post_instrument_id": "ESH6.XCME", "roll_date": "2025-12-18"}
])); Defensive patterns
Strategy: validation
Validate before calling
if transitions.is_empty() {
anyhow::bail!("continuous_future_transitions must contain at least one row");
} Type guard
fn has_transitions(v: &serde_json::Value) -> bool {
v.as_array().map(|a| !a.is_empty()).unwrap_or(false)
} Try / catch
match engine.subscribe_continuous_future_bars(&cmd) {
Err(e) if e.to_string().contains("transitions must not be empty") => {
eprintln!("contract chain was empty; check the source of continuous_future_transitions");
}
r => r?,
} Prevention
- Verify the contract-chain source returned rows before building params
- Never hard-code an empty transitions array in configs
- Log transitions length at subscription setup for easier debugging
When it happens
Trigger: Passing continuous_future_transitions that parses to an empty list — e.g. an empty JSON array, a chain filtered down to nothing, or a missing/malformed transitions payload that deserializes as empty.
Common situations: Building the transitions array programmatically from a contract-chain query that returned no rows; hand-writing an empty [] in config; a data provider returning no contracts for the root/class.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Continuous future bar subscriptions require an internally ag
- Cannot subscribe continuous future bars for {target_bar_type
- No continuous future subscription state for {target_bar_type
- Continuous future bar subscriptions must not include `bar_ty
- Continuous future target {primary_bar_type} must be internal
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d722cd8b7800d0cc.
Report an issue: GitHub.