{"record":{"id":"660bac8d9dee39b2","repo":"nautechsystems/nautilus_trader","slug":"invalid-step-step-must-be-non-zero","errorCode":null,"errorMessage":"Invalid step: {step} (must be non-zero)","messagePattern":"Invalid step: (.+?) \\(must be non-zero\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/bar.rs","lineNumber":490,"sourceCode":"impl BarSpecification {\n    /// Creates a new [`BarSpecification`] instance with correctness checking.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if `step` is not positive (> 0), if `step` is not\n    /// valid for a fixed-subunit time aggregation, or if a time-aggregated\n    /// `step` overflows the representable duration or nanosecond interval.\n    ///\n    /// # Notes\n    ///\n    /// PyO3 requires a `Result` type for proper error handling and stacktrace printing in Python.\n    pub fn new_checked(\n        step: usize,\n        aggregation: BarAggregation,\n        price_type: PriceType,\n    ) -> anyhow::Result<Self> {\n        let step = NonZeroUsize::new(step)\n            .ok_or(anyhow::anyhow!(\"Invalid step: {step} (must be non-zero)\"))?;\n        Self::validate_step(step.get(), aggregation)?;\n\n        Ok(Self {\n            step,\n            aggregation,\n            price_type,\n        })\n    }\n\n    fn validate_step(step: usize, aggregation: BarAggregation) -> anyhow::Result<()> {\n        match aggregation {\n            BarAggregation::Millisecond => {\n                Self::validate_periodic_step(step, aggregation, 1000, false)?;\n            }\n            BarAggregation::Second | BarAggregation::Minute => {\n                Self::validate_periodic_step(step, aggregation, 60, false)?;\n            }\n            BarAggregation::Hour => Self::validate_periodic_step(step, aggregation, 24, false)?,","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/bar.rs#L472-L508","documentation":"BarAggregation's constructor `new_checked` requires the aggregation step to be non-zero. The step is stored as `NonZeroUsize` because a zero step would make bar aggregation meaningless (or cause division-by-zero logic downstream). Passing 0 is rejected immediately with this anyhow error.","triggerScenarios":"Calling `BarAggregation::new_checked(0, aggregation, price_type)` — or building one from a config value that defaulted to or was parsed as 0 — triggers the error before `validate_step` even runs.","commonSituations":"Config files where a step field was omitted and defaulted to 0; deserializing a strategy config where step was typed as a plain usize with a Default derive; a calculation producing a 0 step (e.g. multiplying by 0 or an empty tick count).","solutions":["Check the step value before constructing: reject or default any step == 0 in your config-loading code.","If step comes from a config file, verify the field is present and set to >= 1 (e.g. `step = 100` for 100-tick bars).","If step is computed, add an assertion/log when the computation yields 0 so the bug is caught at the source.","Prefer constructing via `NonZeroUsize::new(step)` yourself at the call site to surface zero values early with your own context."],"exampleFix":"// before\nlet agg = BarAggregation::new_checked(cfg.step, BarAggregation::Tick, PriceType::Last)?;\n\n// after\nlet step = cfg.step.max(1);\nlet agg = BarAggregation::new_checked(step, BarAggregation::Tick, PriceType::Last)?;","handlingStrategy":"validation","validationCode":"fn valid_step(step: usize) -> bool { step != 0 }\nif !valid_step(cfg.step) { return Err(anyhow!(\"step must be non-zero, got {}\", cfg.step)); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store step as NonZeroUsize in your own config types so zero is unrepresentable.","Validate bar aggregation config at startup before any data flow begins.","Use derive defaults like #[serde(default = \"default_step\")] returning 1 instead of 0."],"tags":["rust","validation","bar-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"}