tracel-ai/burn · critical
BURN_DEVICE=ndarray requested, but the 'ndarray' feature is
Error message
BURN_DEVICE=ndarray requested, but the 'ndarray' feature is not enabled.
What it means
This panic fires when BURN_DEVICE=ndarray is requested but the burn build was compiled without the 'ndarray' feature. Backend selection via BURN_DEVICE is a runtime override over backends enabled at compile time; if the ndarray backend was not compiled in, the dispatcher cannot construct an NdArrayDevice and panics instead of silently substituting another backend.
Source
Thrown at crates/burn-dispatch/src/device.rs:285
}
"remote" => {
#[cfg(feature = "remote")]
return Self::Remote(RemoteDevice::default());
panic!(
"BURN_DEVICE=remote requested, but the 'remote' feature is not enabled."
);
}
"flex" => {
#[cfg(any(feature = "flex", default_backend))]
return Self::Flex(FlexDevice);
panic!(
"BURN_DEVICE=flex requested, but the 'flex' feature is not enabled."
);
}
"ndarray" => {
#[cfg(feature = "ndarray")]
return Self::NdArray(NdArrayDevice::default());
panic!(
"BURN_DEVICE=ndarray requested, but the 'ndarray' feature is not enabled."
);
}
_ => panic!("Unknown BURN_DEVICE override: '{}'.", device_str),
}
}
}
// Spelled out per feature rather than left to `CubeDevice::default()`: that answers for
// the runtimes *cubecl* compiled in, and cargo unifies features across a build, so a
// workspace that also builds `burn-cuda` would hand this crate a CUDA default even when
// it was built with only `wgpu`. The order is the one a caller who did not choose would
// want — a discrete accelerator, then the portable path, then the CPU.
#[cfg(feature = "cuda")]
return Self::Cube(CubeDevice::Cuda(Default::default()));
#[cfg(feature = "metal")]
return Self::Cube(CubeDevice::Wgpu(Default::default()));View on GitHub (pinned to d16f7ba2ed)
Solutions
- Enable the feature: burn = { version = "...", features = ["ndarray"] } in Cargo.toml, then rebuild.
- Or enable the unified default_backend-ndarray feature so the env override resolves through the default backend path.
- If ndarray was never intended, unset BURN_DEVICE or set it to an enabled backend (cubecl/candle/flex as compiled).
- Document required BURN_DEVICE values alongside the feature list so env and build stay in sync.
Example fix
// before
[dependencies]
burn = { version = "0.18", features = ["candle"] }
// BURN_DEVICE=ndarray ./app -> panics
// after
[dependencies]
burn = { version = "0.18", features = ["candle", "ndarray"] }
// BURN_DEVICE=ndarray ./app -> NdArrayDevice::default() Defensive patterns
Strategy: validation
Validate before calling
let req = std::env::var("BURN_DEVICE").unwrap_or_default();
if req == "ndarray" && !cfg!(feature = "ndarray") {
panic!("Rebuild with burn feature 'ndarray' or unset BURN_DEVICE");
} Prevention
- Pin the backend in CI both via features and via BURN_DEVICE so they cannot drift.
- Add a startup feature check before device construction.
- Avoid sharing shell profiles that export BURN_DEVICE across differently-built binaries.
When it happens
Trigger: Setting BURN_DEVICE=ndarray in the environment while the binary was built without `features = ["ndarray"]` in the burn dependency; the panic originates from the "ndarray" match arm in device.rs backend parsing.
Common situations: Running tests or scripts that assume the lightweight ndarray backend (common in CI for speed) against a build configured for GPU-only features; inheriting BURN_DEVICE from a shared shell profile or Kubernetes manifest while the binary has different features.
Related errors
- BURN_DEVICE=flex requested, but the 'flex' feature is not en
- Unknown BURN_DEVICE override: '{}'.
- Requires `autodiff` feature
- capture tensor operations must run inside CaptureDevice::cap
- capture tensor {} has no initialized value
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/395a287591d28ee7.
Report an issue: GitHub.