nautechsystems/nautilus_trader · error · ValueError

A BacktestNode is required for the bars_with_fills chart

Error message

A BacktestNode is required for the bars_with_fills chart

What it means

The Betfair data client's HTTP connect step failed; the message re-wraps the underlying BetfairHttpError from BetfairHttpClient::connect(), which performs interactive (non-certificate) login against the Betfair Identity API. Common causes are rejected credentials (LoginFailed), network/DNS/TLS failures, or a proxy misconfiguration. The abort happens before instruments are loaded, so the data client never reaches the streaming stage.

Source

Thrown at python/nautilus_trader/analysis/tearsheet.py:500

    def generate_fills_report(self) -> pd.DataFrame:
        return self._node.generate_fills_report(self._run_config_id)


def _create_tearsheet_from_result(
    result: BacktestResult,
    node: BacktestNode | None,
    run_config_id: str | None,
    currency,
    output_path: str | None,
    title: str,
    config,
    benchmark_returns: pd.Series | None,
    benchmark_name: str,
) -> str | None:
    resolved_run_config_id = run_config_id or result.run_config_id
    needs_engine = config is not None and "bars_with_fills" in config.chart_names
    if needs_engine and node is None:
        raise ValueError("A BacktestNode is required for the bars_with_fills chart")
    if node is not None and resolved_run_config_id is None:
        raise ValueError("run_config_id is required when a BacktestNode is provided")
    if node is not None and resolved_run_config_id is not None:
        _validate_result_node_state(node, resolved_run_config_id)

    engine_view = (
        _BacktestNodeEngineView(node, resolved_run_config_id)
        if node is not None and resolved_run_config_id is not None
        else None
    )
    returns = _result_returns_series(result)
    run_info = _result_run_info(result)
    account_info = _result_account_info(result, node, resolved_run_config_id, currency)

    if title == "NautilusTrader Backtest Results":
        run_started = _format_optional_iso8601(result.run_started)
        title = f"<b>NautilusTrader</b> v{NAUTILUS_VERSION} - Backtest Results"
        title += f"<br><sub>Run started: {run_started}</sub>"

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Verify credentials and app key directly (check BETFAIR_* values, confirm the app key is active)
  2. Test egress with curl to https://identitysso.betfair.com/api/login from the same environment and fix proxy/firewall/CA issues
  3. Retry with exponential backoff - transient failures during Betfair incidents recover
  4. If the underlying error is a login rejection (is_login_failed), fix credentials instead of retrying

Example fix

// before: first failure is fatal
self.http_client.connect().await?;

// after: distinguish auth rejection from transient failure
let mut backoff = std::time::Duration::from_secs(1);
loop {
    match self.http_client.connect().await {
        Ok(()) => break,
        Err(e) if e.is_login_failed() => return Err(e.into()),
        Err(e) if retries_left => {
            tokio::time::sleep(backoff).await;
            backoff *= 2;
        }
        Err(e) => return Err(e.into()),
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// preflight: confirm egress and credential vars before starting the node
let ok = tokio::time::timeout(
    std::time::Duration::from_secs(5),
    reqwest::get("https://identitysso.betfair.com/api/login"),
).await.is_ok();
anyhow::ensure!(ok, "no egress to Betfair Identity API");
anyhow::ensure!(
    std::env::var("BETFAIR_USERNAME").is_ok()
        && std::env::var("BETFAIR_PASSWORD").is_ok()
        && std::env::var("BETFAIR_APP_KEY").is_ok(),
    "credentials not configured"
);

Try / catch

match http_client.connect().await {
    Err(e) if e.is_login_failed() => {
        // credentials rejected: fix config/env, do not retry
    }
    Err(e) => {
        // transport/transient: log and retry with exponential backoff
    }
    Ok(()) => { /* proceed to instrument load */ }
}

Prevention

When it happens

Trigger: Starting/connecting the data client with wrong username or password (LoginFailed from Identity API); firewall, corporate proxy, or DNS blocking identitysso.betfair.com:443; container missing CA certificates; Betfair Identity API outage during login.

Common situations: Password rotated but BETFAIR_PASSWORD stale; VPN or corporate egress blocking Betfair; Docker image without current CA certs; Betfair maintenance window; system clock skew breaking TLS validation.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/1541b075a3d50c51. Report an issue: GitHub.