tracel-ai/burn · critical
capture tensor operations must run inside CaptureDevice::cap
Error message
capture tensor operations must run inside CaptureDevice::capture_scope
What it means
CaptureDevice requires that all tensor operations on its clients run inside `CaptureDevice::capture_scope`. When code obtains a client via `get_client` (e.g. during client initialization or lazy client creation) and no capture scope has registered a client, this panic fires. It is a misuse guard: the capture graph only exists while a scope is active.
Source
Thrown at crates/burn-capture/src/capture.rs:349
///
/// Capture clients are scope-specific: [`CaptureDevice::capture_scope`] creates the client and
/// installs it with `register_scoped_client` before any tensor operations run. An unscoped client
/// would have no lifecycle owner or completed graph boundary, so it is intentionally unsupported.
#[derive(Clone)]
pub struct CaptureChannel;
impl RouterChannel for CaptureChannel {
type Device = CaptureDevice;
type Bridge = CaptureBridge;
type Client = CaptureClient;
fn name(_device: &Self::Device) -> String {
"capture".into()
}
fn init_client(_device: &Self::Device) -> Self::Client {
// `get_client` reaches this only when no capture scope registered its client first.
panic!("capture tensor operations must run inside CaptureDevice::capture_scope")
}
fn get_tensor_handle(tensor: &TensorIr, client: &Self::Client) -> TensorData {
client
.state()
.lock()
.value(tensor.id)
.unwrap_or_else(|| panic!("capture tensor {} has no initialized value", tensor.id))
}
fn register_tensor(
client: &Self::Client,
handle: TensorData,
_shape: Shape,
_dtype: DType,
) -> RouterTensor<Self::Client> {
client.register_tensor_data(handle)
}View on GitHub (pinned to d16f7ba2ed)
Solutions
- Wrap all tensor creation/usage for this device inside `CaptureDevice::capture_scope(|device| { ... })`.
- Move module construction or client initialization into the capture scope closure.
- Do not return capture-device tensors out of the scope; convert/extract results (e.g. into a tensor on a real backend) inside the scope.
Example fix
// before
let tensor = Tensor::<CaptureDevice, 2>::ones([2, 2], &device);
device.capture_scope(|_d| { /* ... */ });
// after
device.capture_scope(|device| {
let tensor = Tensor::<CaptureDevice, 2>::ones([2, 2], device);
// use tensor here
}); Defensive patterns
Strategy: validation
Validate before calling
// Enter the scope before creating any capture tensors
let result = device.capture_scope(|device| {
let t = Tensor::<CaptureDevice, 2>::ones([2, 2], device);
t.into_data() // extract results inside the scope
}); Prevention
- Never construct CaptureDevice tensors outside capture_scope
- Never leak captured tensors out of the closure; convert to data or a real-backend tensor inside
- Initialize modules inside the capture scope if they lazily create tensors
When it happens
Trigger: Calling any tensor operation on a CaptureDevice tensor outside of `device.capture_scope(...)`; constructing or lazily initializing a CaptureDevice client (init_client path) before entering a capture scope; holding a captured tensor beyond the scope and using it later.
Common situations: Creating capture tensors at module init time before the scope starts; storing captured tensors in a struct field and using them after `capture_scope` returns; mixing CaptureDevice with code paths that internally call `get_client` (e.g. lazy backend init).
Related errors
- capture tensor {} has no initialized value
- seeding is not supported during graph capture
- capture graph {graph_id:?} was not registered
- Tensor is on the wrong backend (expected {backend}).
- Autodiff float tensor is on the wrong backend (expected {bac
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/781991b5875c607e.
Report an issue: GitHub.