{"record":{"id":"fd39c2d5f04e6cf1","repo":"nautechsystems/nautilus_trader","slug":"dydx-only-supports-external-aggregation-was","errorCode":null,"errorMessage":"dYdX only supports EXTERNAL aggregation, was {:?}","messagePattern":"dYdX only supports EXTERNAL aggregation, was (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/http/client.rs","lineNumber":116,"sourceCode":"        enums::{DydxCandleResolution, DydxNetwork},\n        instrument_cache::InstrumentCache,\n        parse::extract_raw_symbol,\n    },\n    http::parse::{parse_account_state_from_http, parse_instrument_any},\n};\n\n/// Maximum number of candles returned per dYdX API request.\nconst DYDX_MAX_BARS_PER_REQUEST: u32 = 1_000;\n\n/// Perpetual markets endpoint (shared between `get_markets` and `get_market`).\nconst ENDPOINT_PERPETUAL_MARKETS: &str = \"/v4/perpetualMarkets\";\n\nconst QUERY_MARKET_TYPE_PERPETUAL: &str = \"marketType=PERPETUAL\";\nconst DYDX_INDEXER_REPORT_LIMIT: u32 = 1_000;\n\nfn bar_type_to_resolution(bar_type: &BarType) -> anyhow::Result<DydxCandleResolution> {\n    if bar_type.aggregation_source() != AggregationSource::External {\n        anyhow::bail!(\n            \"dYdX only supports EXTERNAL aggregation, was {:?}\",\n            bar_type.aggregation_source()\n        );\n    }\n\n    let spec = bar_type.spec();\n    if spec.price_type != PriceType::Last {\n        anyhow::bail!(\n            \"dYdX only supports LAST price type, was {:?}\",\n            spec.price_type\n        );\n    }\n\n    DydxCandleResolution::from_bar_spec(&spec)\n}\n\n/// Default dYdX Indexer REST API rate limit.\n///","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/http/client.rs#L98-L134","documentation":"dYdX provides raw candle data via its Indexer HTTP API, so the adapter can only build bars with EXTERNAL aggregation source. `bar_type_to_resolution` (used by `request_bars`) rejects any BarType whose aggregation source is INTERNAL since the adapter cannot supply internal-aggregated bars.","triggerScenarios":"Calling `request_bars` with a BarType constructed with `AggregationSource::Internal`, e.g. `BarType::new(instrument_id, BarSpecification::new(1, BarAggregation::Minute, PriceType::Last), AggregationSource::Internal)`.","commonSituations":"Copying bar request code from adapters that support internal aggregation; a data engine configured to aggregate internally rather than requesting external bars from the venue.","solutions":["Construct the BarType with `AggregationSource::External`","If internal aggregation is desired, request EXTERNAL bars from dYdX and let the data engine aggregate separately"],"exampleFix":"// before\nlet bar_type = BarType::new(instrument_id, spec, AggregationSource::Internal);\n// after\nlet bar_type = BarType::new(instrument_id, spec, AggregationSource::External);","handlingStrategy":"validation","validationCode":"assert_eq!(bar_type.aggregation_source(), AggregationSource::External, \"dYdX requires EXTERNAL aggregation\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Centralize bar-type construction for dYdX in one helper that hardcodes External","Never copy bar-type factories from adapters that support internal aggregation"],"tags":["rust","dydx","bars","aggregation"],"backgroundTag":"invalid-enum-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"}