{"record":{"id":"d232edf14d0ff3ea","repo":"nautechsystems/nautilus_trader","slug":"invalid-bar-specification-format","errorCode":null,"errorMessage":"Invalid bar specification format: {}","messagePattern":"Invalid bar specification format: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/historical/client.rs","lineNumber":330,"sourceCode":"\n        if all_contracts.is_empty() {\n            anyhow::bail!(\"No valid contracts found after conversion\");\n        }\n\n        let trading_hours = if use_rth {\n            TradingHours::Regular\n        } else {\n            TradingHours::Extended\n        };\n\n        let mut all_bars = Vec::new();\n\n        for contract in all_contracts {\n            for bar_spec_str in &bar_specifications {\n                // Parse bar spec (e.g., \"1-HOUR-LAST\")\n                let parts: Vec<&str> = bar_spec_str.split('-').collect();\n                if parts.len() != 3 {\n                    anyhow::bail!(\"Invalid bar specification format: {}\", bar_spec_str);\n                }\n\n                let step = parts[0].parse::<usize>()?;\n                let aggregation = parts[1].to_lowercase();\n                let price_type = parts[2].to_uppercase();\n\n                let bar_spec = match aggregation.as_str() {\n                    \"second\" => BarSpecification::new(\n                        step,\n                        BarAggregation::Second,\n                        PriceType::from_str(&price_type).unwrap_or(PriceType::Last),\n                    ),\n                    \"minute\" => BarSpecification::new(\n                        step,\n                        BarAggregation::Minute,\n                        PriceType::from_str(&price_type).unwrap_or(PriceType::Last),\n                    ),\n                    \"hour\" => BarSpecification::new(","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/historical/client.rs#L312-L348","documentation":"Each bar specification string must be in the three-part form \"<step>-<aggregation>-<price_type>\", e.g. \"1-HOUR-LAST\". request_bars splits on '-' and requires exactly 3 parts; anything else is rejected before parsing.","triggerScenarios":"Passing strings like \"1-HOUR\" (missing price type), \"1HOUR-LAST\" (no separators), \"1-MINUTE-LAST-EXTRA\", or an empty string in bar_specifications.","commonSituations":"Config files with specs written in shorthand (\"1h\", \"5min\"); copying IB's native bar size strings (\"1 hour\") instead of Nautilus bar spec format; trailing whitespace or stray hyphens.","solutions":["Write specs as exactly three hyphen-separated parts, e.g. \"1-MINUTE-LAST\", \"5-HOUR-BID\".","Verify each entry has exactly two '-' characters and no empty segments.","Fix the source config list producing malformed spec strings."],"exampleFix":"// before\nlet specs = vec![\"1-HOUR\"];\n// after\nlet specs = vec![\"1-HOUR-LAST\"];","handlingStrategy":"validation","validationCode":"fn valid_bar_spec(s: &str) -> bool {\n    s.split('-').filter(|p| !p.is_empty()).count() == 3\n}\nlet specs: Vec<&str> = raw.into_iter().filter(|s| valid_bar_spec(s)).collect();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep bar specs in the '<int>-<unit>-<PRICE_TYPE>' form; add unit tests for each configured spec.","Avoid hand-writing specs in YAML/JSON: use constants like \"1-HOUR-LAST\".","Trim whitespace before validation."],"tags":["invalid-format","bar-specification","rust","parsing"],"backgroundTag":"invalid-argument-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"}