{"record":{"id":"451b1827c402ef81","repo":"tracel-ai/burn","slug":"linalg-svd-gradients-are-not-implemented-detach","errorCode":null,"errorMessage":"linalg::svd: gradients are not implemented; detach the input tensor first","messagePattern":"linalg::svd: gradients are not implemented; detach the input tensor first","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-tensor/src/tensor/linalg/svd.rs","lineNumber":97,"sourceCode":"///     // A = U @ diag(S) @ Vt (within tolerance)\n///     let recon = u.mul(s.unsqueeze_dim(0)).matmul(vt);\n///     println!(\"{}\", recon);\n/// }\n/// ```\npub fn svd<const D: usize, const D1: usize>(\n    mut tensor: Tensor<D>,\n    sweeps: usize,\n) -> (Tensor<D>, Tensor<D1>, Tensor<D>) {\n    let dims = tensor.dims();\n    let original_dtype = tensor.dtype();\n    let device = tensor.device();\n    check!(TensorCheck::svd_input_tensor::<D, D1>(\n        \"linalg::svd\",\n        &dims,\n        original_dtype\n    ));\n    if tensor.is_require_grad() {\n        panic!(\"linalg::svd: gradients are not implemented; detach the input tensor first\");\n    }\n    assert!(sweeps > 0, \"linalg::svd: sweeps must be greater than zero\");\n\n    // Upcast f16/bf16 to f32 (same convention as `det`), cast back at the end.\n    let needs_upcast = original_dtype == DType::F16 || original_dtype == DType::BF16;\n    if needs_upcast {\n        tensor = tensor.cast(FloatDType::F32);\n    }\n\n    // One-sided formulation requires m >= n; decompose A^T for wide matrices.\n    let (n_rows, n_cols) = (dims[D - 2], dims[D - 1]);\n    let (a, swap) = if n_rows >= n_cols {\n        (tensor, false)\n    } else {\n        (tensor.transpose(), true)\n    };\n    let (m, n) = (n_rows.max(n_cols), n_rows.min(n_cols));\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-tensor/src/tensor/linalg/svd.rs#L79-L115","documentation":"Autodiff-support guard in `linalg::svd`: SVD has no implemented backward pass, so calling it on a tensor that requires gradients (tracked by autodiff) panics with instructions to detach. The failing input is a tracked tensor passed to svd; detaching breaks the graph edge, making the op legal but non-differentiable.","triggerScenarios":"Thrown at crates/burn-tensor/src/tensor/linalg/svd.rs:97 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Call `.detach()` on the tensor before svd when no gradient through the decomposition is needed.","Compute SVD inside `no_grad`-equivalent contexts, or restructure training so SVD is on a non-differentiable branch.","Implement or wait for an SVD backward (e.g. via the closed-form gradient involving U, S, V) if gradients through SVD are required."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}