nautechsystems/nautilus_trader · error · anyhow::Error
Invalid step in bar spec '{value}': {e}
Error message
Invalid step in bar spec '{value}': {e} What it means
After extracting the leading digit run from the last part of a bar spec, parse_bar_spec parses it as usize. If that parse fails (e.g. a number too large for usize, or digits interleaved with later characters) the error wraps the std ParseIntError with the offending spec value.
Source
Thrown at crates/adapters/tardis/src/common/parse.rs:337
/// The [`PriceType`] is always `LAST` for Tardis trade bars.
///
/// # Errors
///
/// Returns an error if the specification format is invalid or if the aggregation suffix is unsupported.
pub fn parse_bar_spec(value: &str) -> anyhow::Result<BarSpecification> {
let parts: Vec<&str> = value.split('_').collect();
let last_part = parts
.last()
.ok_or_else(|| anyhow::anyhow!("Invalid bar spec: empty string"))?;
let split_idx = last_part
.chars()
.position(|c| !c.is_ascii_digit())
.ok_or_else(|| anyhow::anyhow!("Invalid bar spec: no aggregation suffix in '{value}'"))?;
let (step_str, suffix) = last_part.split_at(split_idx);
let step: usize = step_str
.parse()
.map_err(|e| anyhow::anyhow!("Invalid step in bar spec '{value}': {e}"))?;
let aggregation = match suffix {
"ms" => BarAggregation::Millisecond,
"s" => BarAggregation::Second,
"m" => BarAggregation::Minute,
"ticks" => BarAggregation::Tick,
"vol" => BarAggregation::Volume,
_ => anyhow::bail!("Unsupported bar aggregation type: '{suffix}'"),
};
parse_canonical_bar_spec(step, aggregation)
.with_context(|| format!("Invalid bar spec '{value}'"))
}
fn parse_canonical_bar_spec(
step: usize,
aggregation: BarAggregation,
) -> anyhow::Result<BarSpecification> {View on GitHub (pinned to 18893faf8b)
Solutions
- Check the spec value in the error message — the step must fit in usize and be a plain digit run
- Use a realistic aggregation step (1, 5, 60, 100...) in your bar spec
- Bound/validate the step value at config load before calling parse_bar_spec
- If steps come from user input, clamp to supported aggregation ranges
Example fix
// before
let bar = parse_bar_spec("99999999999999999999m")?; // usize overflow
// after: validate step first
let step: u64 = step_str.parse()?;
anyhow::ensure!(step <= 86_400, "step too large");
let bar = parse_bar_spec(&format!("{step}m"))?; Defensive patterns
Strategy: validation
Validate before calling
fn step_in_range(value: &str) -> bool {
value.rsplit('_').next()
.and_then(|last| last.chars().position(|c| !c.is_ascii_digit()).map(|i| &last[..i]))
.and_then(|s| s.parse::<u64>().ok())
.map(|step| step > 0 && step <= 86_400)
.unwrap_or(false)
} Try / catch
match parse_bar_spec(spec) {
Ok(bar) => /* proceed */,
Err(e) if e.to_string().contains("Invalid step") => {
log::error!("unparseable step in '{spec}'");
return Err(e.into());
}
Err(e) => return Err(e.into()),
} Prevention
- Keep aggregation steps small and realistic (<= 86400)
- Clamp template-generated steps to supported ranges
- Validate the numeric portion before calling parse_bar_spec
When it happens
Trigger: Calling parse_bar_spec with a step that overflows usize (e.g. "99999999999999999999m") or a malformed step where parse cannot handle the extracted digit string.
Common situations: Corrupted config values with absurd aggregation steps; a hand-typed bar spec with a typo in the numeric portion; generated specs from a template with an unbounded substitution.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid bar spec: empty string
- Invalid bar spec: no aggregation suffix in '{value}'
- Unsupported bar aggregation type: '{suffix}'
- Invalid receipt log quantity
- Invalid `external_order_claims` instrument ID {claim}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/1b7d3ab6fb0a9aaa.
Report an issue: GitHub.