{"record":{"id":"98e8605c71c1dd9c","repo":"tracel-ai/burn","slug":"ctc-loss-backward-2-max-target-len-1-exc","errorCode":null,"errorMessage":"ctc_loss_backward: 2 * max_target_len + 1 = {} exceeds the kernel's shared-memory alpha capacity ({}). Reduce target length or raise SHARED_ALPHA_CAPACITY.","messagePattern":"ctc_loss_backward: 2 \\* max_target_len \\+ 1 = (.+?) exceeds the kernel's shared-memory alpha capacity \\((.+?)\\)\\. Reduce target length or raise SHARED_ALPHA_CAPACITY\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-cubecl/src/kernel/ctc.rs","lineNumber":610,"sourceCode":") -> (CubeTensor, CubeTensor, CubeTensor) {\n    // Manual stride indexing below requires a contiguous physical layout;\n    // fusion-produced tensors may arrive with layouts that break that\n    // assumption. No-op when already contiguous.\n    let log_probs = into_contiguous(log_probs);\n    let targets = into_contiguous(targets);\n    let input_lengths = into_contiguous(input_lengths);\n    let target_lengths = into_contiguous(target_lengths);\n\n    let log_probs_shape = log_probs.shape();\n    let [max_input_length, batch_size, _c] = log_probs_shape.dims::<3>();\n    let target_shape = targets.shape();\n    let max_target_len = target_shape.dims::<2>()[1];\n    let max_l_prime = 2 * max_target_len + 1;\n\n    assert!(\n        max_l_prime as u32 <= SHARED_ALPHA_CAPACITY,\n        \"ctc_loss_backward: 2 * max_target_len + 1 = {} exceeds the kernel's shared-memory \\\n         alpha capacity ({}). Reduce target length or raise SHARED_ALPHA_CAPACITY.\",\n        max_l_prime,\n        SHARED_ALPHA_CAPACITY,\n    );\n\n    let hw_max = log_probs.client.properties().hardware.max_cube_dim.0;\n    let cube_dim_x = (max_l_prime as u32).min(hw_max).min(256);\n\n    let client = log_probs.client.clone();\n    let device = log_probs.device.clone();\n    let f_dtype = log_probs.dtype;\n    let i_dtype = targets.dtype;\n\n    // Pre-fill alpha/beta with -inf so positions the kernel doesn't touch\n    // (s >= 2U+1, or t outside the valid range for an individual batch\n    // element) are not read as stale zeros by the gradient composition.\n    let shape_abt = Shape::new([max_input_length, batch_size, max_l_prime]);\n    let neg_inf = InputScalar::new(f32::NEG_INFINITY, dtype_to_storage_type(f_dtype));\n    let alpha_out = crate::ops::numeric::full_device_dtype(","sourceCodeStart":592,"sourceCodeEnd":628,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-cubecl/src/kernel/ctc.rs#L592-L628","documentation":"RouterChannel::change_client_backend panics when the tensor description's dtype is neither float, int, nor bool. The router dispatches dtype-specific bridge calls (change_backend_float/int/bool) and has no branch for other dtypes (e.g. QFloat).","triggerScenarios":"Calling change_client_backend (client backend migration, e.g. moving a tensor between backends/devices via register/change_client) on a tensor whose DType is not Float/Int/Bool — practically a quantized (QFloat) tensor.","commonSituations":"Moving a model containing quantized tensors between backends, or a new DType variant added upstream without updating the router's dtype dispatch chain.","solutions":["Do not migrate quantized tensors with change_client_backend; dequantize first, move, then re-quantize on the target backend.","Verify tensor dtype is Float/Int/Bool before attempting backend migration.","If this stems from a newly added DType variant, update burn-router to add the corresponding change_backend_* bridge branch."],"exampleFix":"// before\nhandle.change_client_backend::<B2>(device); // panics for QFloat\n// after\nassert!(!matches!(desc.dtype, DType::QFloat(_)));\nlet float_t = dequantize(q_tensor);\nlet moved = float_t.change_client_backend::<B2>(device);","handlingStrategy":"validation","validationCode":"fn can_migrate(dtype: burn_tensor::DType) -> bool {\n    matches!(dtype, burn_tensor::DType::F32 | burn_tensor::DType::F64\n        | burn_tensor::DType::I32 | burn_tensor::DType::I64\n        | burn_tensor::DType::U32 | burn_tensor::DType::U64\n        | burn_tensor::DType::Bool)\n}\n// call: assert!(can_migrate(desc.dtype)) before change_client_backend","typeGuard":"fn is_quantized(dtype: &burn_tensor::DType) -> bool {\n    matches!(dtype, burn_tensor::DType::QFloat(_))\n}","tryCatchPattern":"std::panic::catch_unwind(std::panic::AssertUnwindSafe(||\n    handle.change_client_backend::<B2>(&device)\n)).map_err(|_| anyhow::anyhow!(\"dtype not supported for backend migration\"))","preventionTips":["Never route QFloat tensors through change_client_backend; dequantize first.","Check desc.dtype before any cross-backend tensor migration.","Pin to a burn version matching your dtype usage; new DType variants may lack router branches.","Write a smoke test migrating each dtype you use."],"tags":["rust","burn-router","dtype","quantization","unimplemented"],"backgroundTag":"unsupported-dtype","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"}