{"record":{"id":"41c90a7a5a8046fb","repo":"tracel-ai/burn","slug":"graph-replay-should-succeed","errorCode":null,"errorMessage":"graph replay should succeed","messagePattern":"graph replay should succeed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-tensor/src/tensor/api/graph.rs","lineNumber":133,"sourceCode":"    ///   Tensors owned by the closure (or by `self`, like the output) are kept\n    ///   alive automatically; tensors the closure only borrowed must outlive\n    ///   the replays.\n    /// - **No concurrent use** — no other stream or thread reads or writes a\n    ///   tensor shared with the graph while the replay executes; the replay is\n    ///   only ordered against work on its own capture stream.\n    /// - **Same-stream refreshes** — input refreshes and output reads are\n    ///   issued on the stream the graph was captured on (the same device\n    ///   thread/client), so they order correctly against the replay rather\n    ///   than racing it with stale or torn data.\n    ///\n    /// On the fallback path (no hardware graph) this simply re-runs the closure\n    /// and is trivially safe.\n    pub unsafe fn replay(&mut self) -> &T {\n        match &self.hardware {\n            Some(graph) => {\n                // Safety: forwarded verbatim from this method's own contract.\n                unsafe { Dispatch::graph_replay(self.device.as_dispatch(), graph) }\n                    .expect(\"graph replay should succeed\");\n            }\n            None => {\n                self.output = (self.closure)();\n            }\n        }\n        &self.output\n    }\n\n    /// The output tensor(s) the graph writes to — stable across replays on the\n    /// hardware path (the same buffer is overwritten each time).\n    pub fn output(&self) -> &T {\n        &self.output\n    }\n\n    /// Whether this graph replays as a hardware dispatch (`true`) or by\n    /// re-running the closure (`false`).\n    pub fn is_hardware(&self) -> bool {\n        self.hardware.is_some()","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-tensor/src/tensor/api/graph.rs#L115-L151","documentation":"GraphHandle::replay() records and executes the captured CUDA/WGPU graph on the device; the dispatch call returns a Result and any backend error (invalid graph, device reset, unsupported op captured) is turned into a panic by this expect. The unsafe method's contract requires the graph to remain valid and replayable.","triggerScenarios":"Calling `graph.replay()` after the underlying device graph was invalidated or the device was reset; a backend whose graph capture includes unsupported operations that fail at replay time; calling replay on a closed/already-released handle.","commonSituations":"CUDA graph capture misuse (capturing streams that performed illegal ops); hot-reload or device-loss recovery paths replaying stale graphs; experimental graph capture on WGPU adapters lacking support.","solutions":["Verify the graph was captured successfully and the device has not been reset before replaying","Re-capture the graph if the device/adapter changed since capture","Check backend support for graph capture/replay (some CUDA/WGPU versions or adapters don't support it)","Fall back to the non-graph closure execution path if replay is unreliable"],"exampleFix":"// before\nunsafe { graph.replay() };\n// after\nif graph_captures_valid && device_healthy {\n    unsafe { graph.replay() };\n} else {\n    output = closure(); // fall back to eager execution\n}","handlingStrategy":"try-catch","validationCode":"if graph.hardware.is_none() || device_was_reset() {\n    // fall back to eager closure execution instead of replay\n    output = closure();\n}","typeGuard":null,"tryCatchPattern":"// replay() itself is unsafe and panics via expect; guard the device state first\nif graph_valid && !device_lost {\n    unsafe { graph.replay() };\n} else {\n    output = (closure)();\n}","preventionTips":["Re-capture graphs after device reset or adapter change","Only capture ops known to be graph-replay-safe on your backend","Keep a non-graph fallback path in hot loops"],"tags":["cuda","graph-capture","gpu","burn-tensor"],"backgroundTag":"cuda-graph-replay-failure","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}