{"record":{"id":"627814dd5b3a3dfc","repo":"tracel-ai/burn","slug":"node-is-needed-but-never-checkpointed","errorCode":null,"errorMessage":"Node {:?} is needed but never checkpointed","messagePattern":"Node (.+?) is needed but never checkpointed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-autodiff/src/checkpoint/builder.rs","lineNumber":225,"sourceCode":"        // from which we use the ids to find them again in the checkpointing actions\n        for (node_id, n_required) in n_required_map {\n            // We find the checkpointing action for node_id. It's likely in checkpointing_actions\n            // so we check there first, otherwise it will be in backup.\n            // Technically it can be there several times but can never be of both types, so we can assume the first we find is fine\n\n            let action = match self\n                .explicit_actions\n                .iter()\n                .position(|action| action.id() == node_id)\n            {\n                Some(pos) => self.explicit_actions.remove(pos),\n                None => {\n                    let pos = self\n                        .backup_actions\n                        .iter()\n                        .position(|action| action.id() == node_id);\n                    self.backup_actions.remove(pos.unwrap_or_else(|| {\n                        panic!(\"Node {:?} is needed but never checkpointed\", node_id)\n                    }))\n                }\n            };\n\n            match action {\n                CheckpointingAction::Computed {\n                    node_id: _,\n                    state_content,\n                } => {\n                    self.checkpoint_compute(backward_states_map, node_id, state_content, n_required)\n                }\n                CheckpointingAction::Recompute {\n                    node_id: _,\n                    retro_forward,\n                } => self.checkpoint_lazy(\n                    backward_states_map,\n                    retro_forward_map,\n                    node_id,","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-autodiff/src/checkpoint/builder.rs#L207-L243","documentation":"In the router interpreter, bool scatter operations only support IndexingUpdateOp::Add (implemented via bool_scatter_or). Any other update op on a bool tensor hits unimplemented!(), because for booleans only the logical-OR accumulation is defined.","triggerScenarios":"Executing a Scatter operation IR on a bool tensor where desc.update is not IndexingUpdateOp::Add (e.g. it is a different IndexingUpdateOp variant such as a set/replace update coming from a traced scalar-op slice-assign).","commonSituations":"Tracing/exporting a model that performs tensor[index] = value (non-additive scatter) on bool tensors and running it through the burn-router; ops that are fine on float/int tensors but have no bool equivalent.","solutions":["Use IndexingUpdateOp::Add semantics for bool scatter, or implement the update manually: invert the mask and multiply/mask the tensor.","Perform the scatter on an int/float tensor instead and convert back to bool afterward.","Only use bool_scatter_or-supported ops (index_put_ with Add) in traced code paths routed through burn-router."],"exampleFix":"// before\ntensor_bool.scatter(dim, indices, value, IndexingUpdateOp::Set); // panics\n// after\ntensor_bool.scatter(dim, indices, value, IndexingUpdateOp::Add); // bool_scatter_or path","handlingStrategy":"validation","validationCode":"fn bool_scatter_supported(update: IndexingUpdateOp) -> bool {\n    matches!(update, IndexingUpdateOp::Add)\n}\n// assert!(bool_scatter_supported(desc.update)) before scattering on a bool tensor","typeGuard":"fn is_add_update(op: &IndexingUpdateOp) -> bool {\n    matches!(op, IndexingUpdateOp::Add)\n}","tryCatchPattern":"std::panic::catch_unwind(std::panic::AssertUnwindSafe(||\n    run_scatter_on_bool(...)\n)).map_err(|_| anyhow::anyhow!(\"bool scatter only supports Add update op\"))","preventionTips":["Only use additive (OR) scatter updates on bool tensors.","Do the scatter in int/float space and cast back to bool.","Avoid non-additive bool scatter in traced/exported graphs routed via burn-router.","Add a trace-time assertion on update ops for bool tensors."],"tags":["rust","burn-router","scatter","bool-tensor","unimplemented"],"backgroundTag":"unsupported-dtype-for-op","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"}