nautechsystems/nautilus_trader · error
Duplicate run config ID '{}'
Error message
Duplicate run config ID '{}' What it means
validate_configs found two BacktestRunConfig entries sharing the same id string; engines are keyed by config id, so duplicates would collide and the node refuses to build.
Source
Thrown at crates/backtest/src/node.rs:322
}
}
Ok(engine)
}
fn validate_configs(configs: &[BacktestRunConfig]) -> anyhow::Result<()> {
// Kernel initialization sets a thread-local MessageBus that can only be
// initialized once per thread, so multiple engines cannot coexist
anyhow::ensure!(
configs.len() <= 1,
"Only one run config per BacktestNode is supported \
(kernel MessageBus is a thread-local singleton)"
);
let mut seen_ids = AHashSet::new();
for config in configs {
anyhow::ensure!(
seen_ids.insert(config.id()),
"Duplicate run config ID '{}'",
config.id()
);
let venue_names: Vec<String> = config
.venues()
.iter()
.map(|v| v.name().to_string())
.collect();
for data_config in config.data() {
if let (Some(start), Some(end)) = (data_config.start_time(), data_config.end_time()) {
anyhow::ensure!(
start <= end,
"Data config start_time ({start}) must be <= end_time ({end})"
);
}View on GitHub (pinned to 18893faf8b)
Solutions
- Assign a unique id to every BacktestRunConfig (e.g. append an index or scenario name)
- Check loops that build configs so the id varies per iteration
- Deduplicate configs by id before constructing the node
Example fix
// before
for scenario in scenarios {
configs.push(BacktestRunConfig::new("run", ...));
}
// after
for (i, scenario) in scenarios.iter().enumerate() {
configs.push(BacktestRunConfig::new(format!("run-{i}"), ...));
} Defensive patterns
Strategy: validation
Validate before calling
let mut seen = std::collections::HashSet::new();
for c in &configs { assert!(seen.insert(c.id()), "duplicate run id: {}", c.id()); } Prevention
- Generate unique ids for every config (index, scenario name, uuid)
- Never reuse a template config's id without renaming
- Deduplicate by id before constructing the node
When it happens
Trigger: Passing two configs whose `id()` returns the same value to `BacktestNode::new` — e.g. cloning a config template and forgetting to change its id, or building configs in a loop with a constant id.
Common situations: Copy-pasted config templates; loop-generated configs using a fixed name; deserialized configs from a file where ids were duplicated.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- No order book data found for instrument '{instrument_id}' wh
- At least one run config is required
- Invalid starting balance: {e}
- Only one run config per BacktestNode is supported (kernel Me
- Data config start_time ({start}) must be <= end_time ({end})
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d360036d7b53a355.
Report an issue: GitHub.