tracel-ai/burn · error
SVD fallback failed: {err}
Error message
SVD fallback failed: {err} What it means
In `float_svd`, when the backend cannot compute SVD on-device, a CPU host fallback (`svd_host_data`) is used. If the host fallback's decomposition routine fails (e.g. the Jacobi sweep iteration fails to converge or produces invalid data), the code panics with `SVD fallback failed: {err}`. The preceding synchronous data read is also guarded with related expect panics.
Source
Thrown at crates/burn-backend/src/backend/ops/tensor.rs:152
/// * `swap` - Whether `tensor` is the transpose of the matrix being decomposed.
///
/// # Panics
///
/// The default implementation panics if the input cannot be read
/// synchronously or if the QR iteration does not converge within the
/// requested sweep budget.
fn float_svd(
tensor: FloatTensor<B>,
sweeps: usize,
swap: bool,
) -> (FloatTensor<B>, FloatTensor<B>, FloatTensor<B>) {
let device = tensor.device();
let msg = "SVD fallback failed to synchronously read tensor data";
let data = try_read_sync(Self::float_into_data(tensor))
.expect(msg)
.expect(msg);
let (u, s, vt) = super::svd::svd_host_data(data, sweeps, swap)
.unwrap_or_else(|err| panic!("SVD fallback failed: {err}"));
(
Self::float_from_data(u, &device),
Self::float_from_data(s, &device),
Self::float_from_data(vt, &device),
)
}
/// Moves the tensor to the given device.
///
/// # Arguments
///
/// * `tensor` - The tensor.
/// * `device` - The device to move the tensor to.
///
/// # Returns
///
/// The tensor on the given device.View on GitHub (pinned to d16f7ba2ed)
Solutions
- Inspect the embedded `{err}` message to see why svd_host_data failed (convergence vs data issue).
- Sanitize the input: remove/replace NaN and Inf values and ensure the matrix is finite before calling svd().
- Increase `sweeps` (iteration budget) or adjust `swap` to give the Jacobi fallback more room to converge.
- Use a backend with native SVD support or compute SVD via a CPU/linalg library (e.g. ndarray/nalgebra) for pathological inputs.
Example fix
// before let (u, s, vt) = tensor.svd(); // after assert!(tensor.clone().into_data().to_vec().iter().all(|v| v.is_finite())); let (u, s, vt) = tensor.svd(); // or fall back to a CPU linalg crate on error
Defensive patterns
Strategy: fallback
Validate before calling
// check input finiteness before SVD let data = tensor.clone().into_data(); assert!(data.value.iter().all(|x: &f32| x.is_finite()), "SVD input has NaN/Inf");
Type guard
fn svd_safe(t: &burn::tensor::Tensor<burn::tensor::backend::Backend, 2>) -> bool {
// finite, non-degenerate 2D input
t.dims()[0] > 0 && t.dims()[1] > 0
} Try / catch
// burn panics rather than returning Result; isolate with catch_unwind if SVD may fail
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| tensor.svd()));
match result {
Ok(usv) => { /* use u, s, vt */ }
Err(_) => { /* fall back to a CPU linalg crate (nalgebra/ndarray) */ }
} Prevention
- Sanitize tensors (NaN/Inf) before decomposition ops.
- Prefer backends with native SVD for heavy linear-algebra workloads.
- Log matrix shape/conditioning before calling svd() on ill-conditioned inputs.
When it happens
Trigger: Calling `tensor.svd()` (float_svd primitive) on a backend without native SVD, where `svd::svd_host_data(data, sweeps, swap)` returns Err — e.g. non-converging Jacobi sweeps, degenerate/NaN/Inf input matrices, or an unsupported matrix shape.
Common situations: Computing SVD on ill-conditioned matrices or matrices containing NaN/Inf; very large matrices exceeding sweep limits; GPU tensors whose sync read returns None; numerically unstable random initialization causing non-convergence.
Related errors
- svd requires a float tensor
- Quantization scheme is not valid for dtype {other:?}
- Can't store native sub-byte values
- {other:?} doesn't support native packing
- capture tensor operations must run inside CaptureDevice::cap
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/a667cabf98bf79b6.
Report an issue: GitHub.