nautechsystems/nautilus_trader · error
Invalid starting balance: {e}
Error message
Invalid starting balance: {e} What it means
Each venue's starting balances are parsed from their string form into Money. If any string is not a valid Money representation (wrong format, bad currency code, malformed amount), parsing fails and the error is wrapped as "Invalid starting balance: {e}".
Source
Thrown at crates/backtest/src/node.rs:227
pub fn dispose(&mut self) {
for engine in self.engines.values_mut() {
engine.dispose();
}
self.engines.clear();
}
}
fn build_engine(config: &BacktestRunConfig) -> anyhow::Result<BacktestEngine> {
let engine_config = config.engine().clone();
let mut engine = BacktestEngine::new(engine_config)?;
for venue_config in config.venues() {
let starting_balances: Vec<Money> = venue_config
.starting_balances()
.iter()
.map(|s| s.parse::<Money>())
.collect::<Result<Vec<_>, _>>()
.map_err(|e| anyhow::anyhow!("Invalid starting balance: {e}"))?;
let default_leverage = venue_config.default_leverage();
let leverages = venue_config.leverages().cloned().unwrap_or_default();
let margin_model = venue_config.margin_model().cloned().map(Into::into);
let modules = venue_config
.modules()
.iter()
.cloned()
.map(Into::into)
.collect();
let fill_model = venue_config
.fill_model()
.cloned()
.unwrap_or_default()
.into();
let fee_model = venue_config.fee_model().cloned().unwrap_or_default().into();
let latency_model = venue_config.latency_model().cloned().map(Into::into);
let sim_config = SimulatedVenueConfig::builder()View on GitHub (pinned to 18893faf8b)
Solutions
- Use the exact Money string format, e.g. "1000000.00 USD" (amount, space, ISO currency code)
- Remove separators/symbols and use a plain decimal amount
- Check for currency codes outside the registered currency list
- Read the inner parse error after "Invalid starting balance:" for the specific cause
Example fix
// before
venue_config.add_starting_balance("$1,000,000.00");
// after
venue_config.add_starting_balance("1000000.00 USD"); Defensive patterns
Strategy: validation
Validate before calling
let money: Money = s.parse().map_err(|e| anyhow!("bad starting balance '{s}': {e}"))?; Try / catch
match s.parse::<Money>() {
Ok(m) => m,
Err(e) => { eprintln!("balance '{s}' invalid: {e}"); return Err(e.into()); }
} Prevention
- Use the canonical Money string format: "<amount> <CURRENCY>"
- Avoid locale-formatted numbers, symbols, and thousands separators
- Validate currency codes against registered currencies
When it happens
Trigger: Providing a venue starting balance string that fails `"...".parse::<Money>()` — e.g. wrong decimal format, missing currency, unknown currency code — in a BacktestVenueConfig passed to BacktestNode::build.
Common situations: Typo in currency code; amounts with thousands separators or symbols; locale-formatted numbers; balance strings copied from a different API with different formatting.
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
- No order book data found for instrument '{instrument_id}' wh
- At least one run config is required
- Only one run config per BacktestNode is supported (kernel Me
- Duplicate run config ID '{}'
- 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/d33d2bff96f8d8a5.
Report an issue: GitHub.