{"record":{"id":"13c2d6e5d1b8a21c","repo":"nautechsystems/nautilus_trader","slug":"data-config-start-time-start-must-be-end-ti","errorCode":null,"errorMessage":"Data config start_time ({start}) must be <= end_time ({end})","messagePattern":"Data config start_time \\((.+?)\\) must be <= end_time \\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/node.rs","lineNumber":336,"sourceCode":"\n    let mut seen_ids = AHashSet::new();\n\n    for config in configs {\n        anyhow::ensure!(\n            seen_ids.insert(config.id()),\n            \"Duplicate run config ID '{}'\",\n            config.id()\n        );\n\n        let venue_names: Vec<String> = config\n            .venues()\n            .iter()\n            .map(|v| v.name().to_string())\n            .collect();\n\n        for data_config in config.data() {\n            if let (Some(start), Some(end)) = (data_config.start_time(), data_config.end_time()) {\n                anyhow::ensure!(\n                    start <= end,\n                    \"Data config start_time ({start}) must be <= end_time ({end})\"\n                );\n            }\n\n            for instrument_id in data_config.get_instrument_ids()? {\n                let venue = instrument_id.venue.to_string();\n                anyhow::ensure!(\n                    venue_names.contains(&venue),\n                    \"No venue config found for venue '{venue}' (required by instrument {instrument_id})\"\n                );\n            }\n        }\n\n        for venue_config in config.venues() {\n            let needs_book_data = matches!(\n                venue_config.book_type(),\n                BookType::L2_MBP | BookType::L3_MBO","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/node.rs#L318-L354","documentation":"validate_configs found a data config whose start_time is later than its end_time; an inverted time range would request negative-duration data, so the node rejects the configuration before building engines.","triggerScenarios":"A BacktestDataConfig whose start_time is strictly after its end_time, passed via BacktestRunConfig to `BacktestNode::new` — e.g. swapped arguments or a computed range that resolved backwards.","commonSituations":"Swapped start/end arguments; computing dates relative to 'now' where timezone or ordering bugs inverted the interval; user-supplied date ranges from a UI or CLI in conflicting order or formats.","solutions":["Swap the values so start_time <= end_time in the data config","Fix the code computing the range (argument order, timezone, unit confusion)","Validate user-supplied date ranges before constructing BacktestDataConfig"],"exampleFix":"// before\nBacktestDataConfig::new(..., start_time: end.into(), end_time: start.into())\n// after\nassert!(start <= end);\nBacktestDataConfig::new(..., start_time: start.into(), end_time: end.into())","handlingStrategy":"validation","validationCode":"if let (Some(s), Some(e)) = (data_config.start_time(), data_config.end_time()) {\n    assert!(s <= e, \"start_time {s} after end_time {e}\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate start/end ordering at config-construction boundaries","Watch for timezone and unit bugs when computing ranges relative to now","Normalize user-supplied date ranges before building BacktestDataConfig"],"tags":["backtest","configuration","date-range"],"backgroundTag":"invalid-date-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}