{"record":{"id":"25ef23cdb9362762","repo":"nautechsystems/nautilus_trader","slug":"bar-type-aggregation-source-must-be-external-was","errorCode":null,"errorMessage":"bar_type.aggregation_source must be External, was {:?}","messagePattern":"bar_type\\.aggregation_source must be External, was (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/engine.rs","lineNumber":488,"sourceCode":"            #[cfg(feature = \"defi\")]\n            let first_is_defi = matches!(first, DataRef::Defi(_));\n            #[cfg(not(feature = \"defi\"))]\n            let first_is_defi = false;\n\n            if !first_is_defi && !matches!(first, DataRef::Custom(_)) {\n                let first_instrument_id = first.instrument_id();\n                anyhow::ensure!(\n                    self.kernel\n                        .cache\n                        .borrow()\n                        .instrument(&first_instrument_id)\n                        .is_some(),\n                    \"Instrument {first_instrument_id} for the given data not found in the cache. \\\n                     Add the instrument through `add_instrument()` prior to adding related data.\"\n                );\n\n                if let DataRef::Bar(bar) = first {\n                    anyhow::ensure!(\n                        bar.bar_type.aggregation_source() == AggregationSource::External,\n                        \"bar_type.aggregation_source must be External, was {:?}\",\n                        bar.bar_type.aggregation_source(),\n                    );\n                }\n            }\n        }\n\n        // Track has_data / has_book_data unconditionally so the depth-vs-data\n        // run-time check still fires for callers that pass validate=false\n        // (e.g. node.rs run_oneshot loading from a catalog). Time bounds are\n        // also tracked here so start/end defaults are correct even when the\n        // batch was added with sort=false.\n        let mut count = 0;\n        let mut batch_min_ts: Option<UnixNanos> = None;\n        let mut batch_max_ts: Option<UnixNanos> = None;\n\n        #[cfg(feature = \"defi\")]","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/engine.rs#L470-L506","documentation":"When registering added Bar data, the backtest engine requires each bar's BarType to have AggregationSource::External, meaning bars arrive pre-aggregated from outside. Internally aggregated bars would need the aggregator machinery the backtest engine does not wire for added data, so it rejects them with this error.","triggerScenarios":"engine.add_data/add_data_batch with DataRef::Bar items whose bar_type.aggregation_source() is Internal — typically bars constructed with BarType::new(..., AggregationSource::Internal) or built via a spec defaulting to Internal.","commonSituations":"Reusing BarTypes created for a live node's internal aggregator; constructing bar types without explicitly setting the source; loading historical bars from a catalog where the bar type was stored with Internal source.","solutions":["Rebuild the bar_type with AggregationSource::External before creating the Bar objects you add.","If bar types come from a catalog/config, map them to External source when loading for backtest.","Aggregate data upstream (e.g. with the data catalog's bar aggregation) and only feed externally aggregated bars."],"exampleFix":"// before\nlet bar_type = BarType::new(instrument_id, BarAggregation::Minute, Price::from(\"1\"), AggregationSource::Internal);\n// after\nlet bar_type = BarType::new(instrument_id, BarAggregation::Minute, Price::from(\"1\"), AggregationSource::External);","handlingStrategy":"validation","validationCode":"if let DataRef::Bar(bar) = first {\n    assert_eq!(bar.bar_type.aggregation_source(), AggregationSource::External,\n        \"bars added to a backtest must use AggregationSource::External\");\n}","typeGuard":"fn is_external_bar(b: &Bar) -> bool {\n    b.bar_type.aggregation_source() == AggregationSource::External\n}","tryCatchPattern":null,"preventionTips":["Always construct bar types with AggregationSource::Explicit/External for backtesting.","Normalize bar types loaded from catalogs/config to External source before adding.","Aggregate bars upstream so the engine only receives finished bars."],"tags":["rust","backtest","bars","validation","aggregation"],"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-14T00:17:10.932Z"}