{"record":{"id":"30cf4a2a6230a3e4","repo":"nautechsystems/nautilus_trader","slug":"backtestnode-state-is-unavailable-when-dispose-on","errorCode":null,"errorMessage":"BacktestNode state is unavailable when dispose_on_completion=True; set dispose_on_completion=False before running the backtest","messagePattern":"BacktestNode state is unavailable when dispose_on_completion=True; set dispose_on_completion=False before running the backtest","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/nautilus_trader/analysis/tearsheet.py","lineNumber":541,"sourceCode":"        stats_pnls=_filter_stats_pnls(result.stats_pnls, currency),\n        stats_returns=result.stats_returns,\n        stats_general=result.stats_general,\n        returns=returns,\n        output_path=output_path,\n        title=title,\n        config=config,\n        benchmark_returns=benchmark_returns,\n        benchmark_name=benchmark_name,\n        engine=engine_view,\n    )\n\n\ndef _validate_result_node_state(node: BacktestNode, run_config_id: str) -> None:\n    for run_config in node.configs:\n        if run_config.id != run_config_id:\n            continue\n        if run_config.dispose_on_completion:\n            raise ValueError(\n                \"BacktestNode state is unavailable when dispose_on_completion=True; \"\n                \"set dispose_on_completion=False before running the backtest\",\n            )\n        return\n\n\ndef _filter_stats_pnls(stats_pnls, currency) -> dict:\n    stats_pnls = dict(stats_pnls)\n    if currency is None:\n        return stats_pnls\n\n    currency_code = getattr(currency, \"code\", str(currency))\n    return {currency_code: stats_pnls[currency_code]} if currency_code in stats_pnls else {}\n\n\ndef _result_returns_series(result: BacktestResult) -> pd.Series:\n    returns = pd.Series(dict(result.returns_series), dtype=\"float64\")\n    returns.index = pd.to_datetime(returns.index, unit=\"ns\", utc=True)","sourceCodeStart":523,"sourceCodeEnd":559,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/python/nautilus_trader/analysis/tearsheet.py#L523-L559","documentation":"BetfairStreamClient::connect failed while establishing the push stream websocket used for market data; the underlying transport or authentication error is re-wrapped as a string. Typical causes are websocket egress blocked while REST is allowed, wrong stream_host/stream_port overrides in BetfairStreamConfig, or the stream endpoint rejecting the session token/app key.","triggerScenarios":"Starting the data client where firewalls or proxies permit HTTPS REST but block the Betfair stream websocket; custom stream_host/stream_port set incorrectly in config; app key without streaming entitlements; Betfair stream endpoint maintenance.","commonSituations":"Corporate networks allowing 443 REST but terminating websockets; config copied from a test environment with stale host overrides; delayed app keys that cannot stream; Betfair stream incidents.","solutions":["Verify websocket egress to the Betfair stream host from the same environment","Remove custom stream_host/stream_port overrides so defaults apply","Confirm the app key has streaming access and the session token is fresh","Retry after Betfair-side incidents clear"],"exampleFix":"// before: single attempt\nlet client = BetfairStreamClient::connect(&cred, token, handler, cfg).await?;\n\n// after: bounded retry with backoff\nlet client = retry_with_backoff(5, |token| async {\n    BetfairStreamClient::connect(&cred, token.clone(), handler.clone(), cfg.clone()).await\n}, token).await?;","handlingStrategy":"retry","validationCode":"// preflight: confirm the stream endpoint is reachable before starting\nlet host = stream_config.host.clone();\nanyhow::ensure!(\n    tokio::net::TcpStream::connect((host.as_str(), stream_config.port)).await.is_ok(),\n    \"no egress to Betfair stream host {host}:{}\",\n    stream_config.port\n);","typeGuard":null,"tryCatchPattern":"match BetfairStreamClient::connect(&cred, token, handler, cfg).await {\n    Ok(client) => { /* proceed */ }\n    Err(e) => {\n        // check for auth/entitlement in the message; retry transient transport\n        // failures with backoff, escalate persistent ones\n    }\n}","preventionTips":["Test websocket egress (not just HTTPS) to the stream host from production","Avoid custom stream_host/stream_port unless required","Confirm the app key has streaming entitlements","Retry stream connect with exponential backoff and a retry cap"],"tags":["betfair","websocket","streaming","network","rust"],"backgroundTag":"websocket-connection-failed","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}