{"record":{"id":"d722cd8b7800d0cc","repo":"nautechsystems/nautilus_trader","slug":"continuous-future-transitions-must-not-be-empty","errorCode":null,"errorMessage":"Continuous future transitions must not be empty","messagePattern":"Continuous future transitions must not be empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/data/src/engine/requests.rs","lineNumber":399,"sourceCode":"        })?;\n    let first_pre_instrument_id = parse_optional_chain_bound(\n        params,\n        FIRST_PRE_INSTRUMENT_ID,\n        primary_bar_type.instrument_id(),\n    )?;\n    let last_post_instrument_id = parse_optional_chain_bound(\n        params,\n        LAST_POST_INSTRUMENT_ID,\n        primary_bar_type.instrument_id(),\n    )?;\n    let transitions = parse_transitions(\n        primary_bar_type,\n        transitions_value,\n        adjustment_mode.is_ratio(),\n    )?;\n\n    if transitions.is_empty() {\n        anyhow::bail!(\"Continuous future transitions must not be empty\");\n    }\n\n    if let Some(instrument_id) = first_pre_instrument_id\n        && !transitions\n            .iter()\n            .any(|row| row.pre_instrument_id == instrument_id)\n    {\n        anyhow::bail!(\n            \"Continuous future first_pre_instrument_id {instrument_id} was not found in transitions\"\n        );\n    }\n\n    if let Some(instrument_id) = last_post_instrument_id\n        && !transitions\n            .iter()\n            .any(|row| row.post_instrument_id == instrument_id)\n    {\n        anyhow::bail!(","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/data/src/engine/requests.rs#L381-L417","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet params = params_with(CONTINUOUS_FUTURE_TRANSITIONS, json!([]));\n// after\nlet params = params_with(CONTINUOUS_FUTURE_TRANSITIONS, json!([\n  {\"pre_instrument_id\": \"ESZ5.XCME\", \"post_instrument_id\": \"ESH6.XCME\", \"roll_date\": \"2025-12-18\"}\n]));","handlingStrategy":"validation","validationCode":"if transitions.is_empty() {\n    anyhow::bail!(\"continuous_future_transitions must contain at least one row\");\n}","typeGuard":"fn has_transitions(v: &serde_json::Value) -> bool {\n    v.as_array().map(|a| !a.is_empty()).unwrap_or(false)\n}","tryCatchPattern":"match engine.subscribe_continuous_future_bars(&cmd) {\n    Err(e) if e.to_string().contains(\"transitions must not be empty\") => {\n        eprintln!(\"contract chain was empty; check the source of continuous_future_transitions\");\n    }\n    r => r?,\n}","preventionTips":["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"],"tags":["rust","data-engine","futures","empty-list"],"backgroundTag":"empty-required-field","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}