nautechsystems/nautilus_trader · error · anyhow::Error
Invalid bar spec: no aggregation suffix in '{value}'
Error message
Invalid bar spec: no aggregation suffix in '{value}' What it means
parse_bar_spec expects the last '_' separated part to begin with a numeric step (e.g. "1m", "100ticks"). If no leading ASCII digits are found in that part, there is no aggregation step, and the function rejects the value with this error naming the original spec string.
Source
Thrown at crates/adapters/tardis/src/common/parse.rs:332
}
}
/// Parses a Nautilus bar specification from the given Tardis string `value`.
///
/// 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}'"))
}View on GitHub (pinned to 18893faf8b)
Solutions
- Check the spec string printed in the error — the final '_' part must start with digits, e.g. "..._1m", "..._100ticks"
- Convert Nautilus-style specs ("1-MINUTE") to the Tardis expected format before parsing
- Ensure futures symbols with month suffixes are not routed into parse_bar_spec
- Validate bar specs at config load to catch the typo early
Example fix
// before
let bar = parse_bar_spec("1-MINUTE")?; // no numeric step in last part
// after: Tardis-style spec
let bar = parse_bar_spec("BTCUSD_1m")?; // step '1' + suffix 'm' Defensive patterns
Strategy: validation
Validate before calling
fn has_numeric_step(value: &str) -> bool {
value.rsplit('_').next()
.map(|last| last.chars().next().map(|c| c.is_ascii_digit()).unwrap_or(false))
.unwrap_or(false)
} Try / catch
match parse_bar_spec(spec) {
Ok(bar) => /* proceed */,
Err(e) if e.to_string().contains("no aggregation suffix") => {
log::error!("malformed bar spec '{spec}': expected '<step><suffix>', e.g. '1m'");
return Err(e.into());
}
Err(e) => return Err(e.into()),
} Prevention
- Use Tardis bar spec syntax: step digits + suffix, e.g. '1m', '100ticks'
- Do not route instrument/futures symbols (with month suffixes) into parse_bar_spec
- Validate spec format at config load
When it happens
Trigger: Calling parse_bar_spec with a spec whose final segment lacks a leading number: "m" (e.g. "BTCUSD_m" with no step), "minute", "1-MINUTE" if the '_' split leaves a non-numeric tail, or a symbol accidentally used as a bar spec.
Common situations: Confusing Tardis bar spec syntax with Nautilus BarSpecification strings; a Tardis symbol suffix like "_m" (month futures) being mistaken for a bar spec; typos in subscription configuration.
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 step in bar spec '{value}': {e}
- Invalid execution time format: {time_str}
- Unsupported bar aggregation type: '{suffix}'
- Venue '{venue_str}' is not a DEX venue (expected format 'Cha
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0695e5100f90127b.
Report an issue: GitHub.