{"record":{"id":"bb3c4cadad61c3de","repo":"nautechsystems/nautilus_trader","slug":"continuous-future-key-venue-mismatch-for-target","errorCode":null,"errorMessage":"Continuous future {key} venue mismatch for {target_instrument_id}: target venue {}, {key} venue {}","messagePattern":"Continuous future (.+?) venue mismatch for (.+?): target venue (.+?), (.+?) venue (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/data/src/engine/requests.rs","lineNumber":506,"sourceCode":"        Some(3) => Ok(ContinuousFutureAdjustmentType::BackwardRatio),\n        Some(4) => Ok(ContinuousFutureAdjustmentType::ForwardRatio),\n        _ => anyhow::bail!(\"failed to parse `{CONTINUOUS_FUTURE_ADJUSTMENT_MODE}`\"),\n    }\n}\n\nfn parse_optional_chain_bound(\n    params: &Params,\n    key: &str,\n    target_instrument_id: InstrumentId,\n) -> anyhow::Result<Option<InstrumentId>> {\n    let Some(raw) = params.get_str(key) else {\n        return Ok(None);\n    };\n\n    let instrument_id = InstrumentId::from_str(raw)\n        .with_context(|| format!(\"Invalid continuous future {key} for {target_instrument_id}\"))?;\n    if instrument_id.venue != target_instrument_id.venue {\n        anyhow::bail!(\n            \"Continuous future {key} venue mismatch for {target_instrument_id}: target venue {}, {key} venue {}\",\n            target_instrument_id.venue,\n            instrument_id.venue,\n        );\n    }\n\n    Ok(Some(instrument_id))\n}\n\nfn parse_transitions(\n    target_bar_type: BarType,\n    value: &Value,\n    is_ratio: bool,\n) -> anyhow::Result<Vec<ContinuousFutureTransition>> {\n    let values = value\n        .as_array()\n        .context(\"Continuous future transitions must be an array\")?;\n    let target_venue = target_bar_type.instrument_id().venue;","sourceCodeStart":488,"sourceCodeEnd":524,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/data/src/engine/requests.rs#L488-L524","documentation":"An optional chain bound (e.g. first/last instrument) parsed for a continuous future is on a different venue than the target continuous instrument. All chain bounds must belong to the same venue as the continuous series itself.","triggerScenarios":"parse_optional_chain_bound is given an instrument ID (via a chain-bound request parameter) whose venue differs from target_instrument_id's venue, e.g. bound \"NQZ5-CME\" for target \"ES.C-...-CME\" is fine, but \"RTYZ5-ICE\" is not.","commonSituations":"Copy-pasting bounds from another exchange's roll table; using the wrong venue suffix (-ICE vs -CME); mixing contract chains across venues in config.","solutions":["Correct the bound's venue suffix so it matches the target continuous instrument's venue.","Verify the bound belongs to the same product family/venue as the continuous series.","Filter bounds by venue before building request params."],"exampleFix":"// before\n\"first_pre_instrument_id\": \"RTYZ5-ICE\" // target is ES...CME\n// after\n\"first_pre_instrument_id\": \"ESZ5-CME\"","handlingStrategy":"validation","validationCode":"assert_eq!(bound.venue, target_instrument_id.venue, \"chain bound venue mismatch\");","typeGuard":"fn same_venue(a: &InstrumentId, b: &InstrumentId) -> bool { a.venue == b.venue }","tryCatchPattern":null,"preventionTips":["Always derive bounds from the same venue as the continuous instrument","Standardize venue suffix constants per product family"],"tags":["validation","venue-mismatch","continuous-futures"],"backgroundTag":"invalid-argument-value","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"}