{"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":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/nautilus_trader/analysis/tearsheet.py","lineNumber":555,"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(\n    stats_pnls: Mapping[str, Any],\n    currency: Currency | None,\n) -> dict[str, Any]:\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","sourceCodeStart":537,"sourceCodeEnd":573,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/python/nautilus_trader/analysis/tearsheet.py#L537-L573","documentation":"The tearsheet reads chart data from the BacktestNode's internal engine state after a run. If the run config had dispose_on_completion=True, the engine is torn down and its state discarded once the backtest finishes, so the library refuses to proceed rather than fail later with missing data.","triggerScenarios":"Running a backtest via BacktestNode whose BacktestRunConfig has dispose_on_completion=True (the teardown/default in some wrappers), then calling create_tearsheet with that node and the matching run_config_id for charts that need engine data (e.g. bars_with_fills).","commonSituations":"Reusing a node from a distributed/parallel run where dispose_on_completion defaults to True; configuring the node for memory efficiency and later adding visualization; following older examples written before tearsheets consumed node state.","solutions":["Set dispose_on_completion=False on the BacktestRunConfig before running the backtest, then re-run.","If the run already completed with disposal, re-execute the backtest with disposal disabled before generating the tearsheet.","Generate tearsheets without node-dependent charts (remove 'bars_with_fills' from chart_names) and pass node=None."],"exampleFix":"// before\nconfig = BacktestRunConfig(...)\nnode = BacktestNode(configs=[config])\nnode.run()\n// after\nconfig = BacktestRunConfig(..., dispose_on_completion=False)\nnode = BacktestNode(configs=[config])\nnode.run()","handlingStrategy":"validation","validationCode":"if node is not None:\n    for rc in node.configs:\n        if rc.dispose_on_completion:\n            raise ValueError(f'Run config {rc.id} has dispose_on_completion=True; tearsheet needs engine state')","typeGuard":null,"tryCatchPattern":"try:\n    path = create_tearsheet(result, config=config, node=node, run_config_id=rid)\nexcept ValueError as e:\n    if 'dispose_on_completion' in str(e):\n        config.dispose_on_completion = False\n        node.run()  # re-run with state retained\n        path = create_tearsheet(result, config=config, node=node, run_config_id=rid)\n    else:\n        raise","preventionTips":["Always set dispose_on_completion=False on run configs that will be visualized.","Build node-based tearsheets immediately after node.run() in the same process.","If running many configs in parallel, keep disposal enabled for non-visualized runs and re-run only the ones needing charts."],"tags":["python","backtesting","state-management"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}