nautechsystems/nautilus_trader · error · ValueError
account report contains multiple currencies
Error message
account report contains multiple currencies
What it means
With subscribe_race_data enabled, the data client queries the session token a second time (after the main stream is up) to connect the race stream at BETFAIR_RACE_STREAM_HOST, and session_token() returned None. Like error 110, the token slot is filled by login and cleared by disconnect/reconnect, so this indicates the session was cleared mid-connect by a concurrent operation, or the session expired and was invalidated between the two reads.
Source
Thrown at python/nautilus_trader/analysis/tearsheet.py:901
currency_report["total"].iloc[-1],
)
return account_info
def _extract_account_balance_series(
report: pd.DataFrame,
target_currency: str | None,
) -> tuple[pd.Series | None, str | None]:
if report.empty or "currency" not in report or "total" not in report:
return None, None
observed_currency: str | None = None
if target_currency is None:
account_currencies = set(report["currency"].dropna())
if len(account_currencies) != 1:
raise ValueError("account report contains multiple currencies")
observed_currency = next(iter(account_currencies))
else:
report = report[report["currency"] == target_currency]
if report.empty:
return None, observed_currency
totals = pd.to_numeric(report["total"], errors="coerce")
totals.index = report.index
totals = totals.dropna().sort_index()
if totals.empty:
return None, observed_currency
return totals.groupby(level=0).last(), observed_currency
def _calculate_daily_balance_returns(total_balance: pd.Series) -> pd.Series | None:
account_returns = (View on GitHub (pinned to a4b06ed870)
Solutions
- Serialize connect/disconnect: one owner task for the HTTP client lifecycle
- Retry connect() to re-login and rebuild both streams
- Defer stop/shutdown signals until connect reports completion
Example fix
// before: read once, fail hard
let race_session = self.http_client.session_token().await
.ok_or_else(|| anyhow::anyhow!("No session token for race stream"))?;
// after: re-login if the slot was cleared
let race_session = match self.http_client.session_token().await {
Some(t) => t,
None => {
self.http_client.reconnect().await?;
self.http_client.session_token().await
.ok_or_else(|| anyhow::anyhow!("No session token for race stream"))?
}
}; Defensive patterns
Strategy: validation
Validate before calling
if config.subscribe_race_data {
anyhow::ensure!(
http_client.is_connected().await,
"session lost before race stream setup; avoid concurrent disconnect during connect"
);
} Type guard
async fn has_live_session(client: &BetfairHttpClient) -> bool {
client.is_connected().await
} Try / catch
match http_client.session_token().await {
Some(t) => { /* open race stream */ }
None => {
// token cleared mid-connect: re-login and rebuild streams once
http_client.reconnect().await?;
}
} Prevention
- Serialize the whole multi-stream connect sequence under one owner
- Delay shutdown signals until connect completes
- Log session lifecycle events to spot racing disconnects
When it happens
Trigger: subscribe_race_data: true in the data config and a concurrent disconnect()/reconnect() on the shared HTTP client between main-stream setup and race-stream setup; stopping the node while race stream setup is in progress.
Common situations: Shutdown during startup; supervision timeouts that disconnect mid-connect; racing owners of the shared HTTP client.
Related errors
- run_config_id is required when a BacktestNode is provided
- height must be positive, was {self.height}
- pandas is required for report generation; install it with `p
- pandas is required for visualization; install it with `pip i
- {name} must not be None
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/0223dce99d3c57f7.
Report an issue: GitHub.