{"record":{"id":"40dcd3d499de13e9","repo":"nautechsystems/nautilus_trader","slug":"data-has-been-added-but-not-sorted-call-engine-s","errorCode":null,"errorMessage":"Data has been added but not sorted, call `engine.sort_data()` or use `engine.add_data(..., sort=true)` before running","messagePattern":"Data has been added but not sorted, call `engine\\.sort_data\\(\\)` or use `engine\\.add_data\\(\\.\\.\\., sort=true\\)` before running","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/engine.rs","lineNumber":730,"sourceCode":"        // and flush callbacks that execute after the main data loop) so the\n        // trader and engines actually stop.\n        // Streaming batches retain commands deferred by other instruments,\n        // and end() performs the unrestricted drain after all batches are loaded.\n        if !streaming || self.force_stop || self.kernel.is_shutdown_requested() {\n            self.end()?;\n        }\n\n        Ok(())\n    }\n\n    fn run_impl(\n        &mut self,\n        start: Option<UnixNanos>,\n        end: Option<UnixNanos>,\n        run_config_id: Option<String>,\n        streaming: bool,\n    ) -> anyhow::Result<()> {\n        anyhow::ensure!(\n            self.sorted,\n            \"Data has been added but not sorted, call `engine.sort_data()` or use \\\n             `engine.add_data(..., sort=true)` before running\"\n        );\n\n        for exchange in self.venues.values() {\n            let exchange = exchange.borrow();\n            let book_type_has_depth = exchange.book_type() as u8 > BookType::L1_MBP as u8;\n            if !book_type_has_depth {\n                continue;\n            }\n\n            for instrument_id in exchange.instrument_ids() {\n                let has_data = self.has_data.contains(instrument_id);\n                let missing_book_data = !self.has_book_data.contains(instrument_id)\n                    && !self.has_book_processed.contains(instrument_id);\n\n                if has_data && missing_book_data {","sourceCodeStart":712,"sourceCodeEnd":748,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/engine.rs#L712-L748","documentation":"The backtest engine requires its internal data to be chronologically sorted before run_impl executes. If data was added without sorting (the engine's `sorted` flag is false), running is refused so the time-driven simulation does not process out-of-order events.","triggerScenarios":"Calling engine.run(...) after add_data/add_data_batch with sort=false (or raw additions without engine.sort_data()); the flag stays false because sort was never invoked.","commonSituations":"Adding data in multiple batches with sort=false for performance and forgetting the final sort_data(); constructing the engine via a custom loader that bypasses the sorted flag; interleaving add_data and add_data_batch calls where the last one had sort=false.","solutions":["Call engine.sort_data() before run().","Pass sort=true to the last add_data/add_data_batch call.","Ensure your data-loading path always ends with a sort; consider sorting once after all batches for efficiency."],"exampleFix":"// before\nengine.add_data_batch(data, false);\nengine.run();\n// after\nengine.add_data_batch(data, false);\nengine.sort_data();\nengine.run();","handlingStrategy":"validation","validationCode":"if !engine_is_sorted() {\n    engine.sort_data(); // or re-add with sort=true\n}\nengine.run(None, None, None, false);","typeGuard":null,"tryCatchPattern":"match engine.run(None, None, None, false) {\n    Err(e) if e.to_string().contains(\"not sorted\") => {\n        engine.sort_data();\n        engine.run(None, None, None, false)?;\n    }\n    r => r?,\n}","preventionTips":["Make the final data-loading step always call sort_data().","Prefer add_data(..., sort=true) unless you deliberately batch-sort.","Add an assertion in your loader that the engine is sorted before run."],"tags":["rust","backtest","ordering","state","validation"],"backgroundTag":"invalid-state-transition","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"}