tracel-ai/burn · error
ctc_loss: 2 * max_target_len + 1 = {} exceeds the kernel's s
Error message
ctc_loss: 2 * max_target_len + 1 = {} exceeds the kernel's shared-memory alpha capacity ({}). Reduce target length or raise SHARED_ALPHA_CAPACITY. What it means
AsyncPolicy::load_record is intentionally unimplemented. An AsyncPolicy spawns a background inference worker holding a clone of the inner policy's state, so a record cannot be loaded directly on the async wrapper; the message tells you to load the record on the inner policy first and then wrap it.
Source
Thrown at crates/burn-cubecl/src/kernel/ctc.rs:307
) -> CubeTensor {
// Manual stride indexing below requires a contiguous physical layout;
// fusion-produced tensors may arrive with layouts that break that
// assumption. No-op when already contiguous.
let log_probs = into_contiguous(log_probs);
let targets = into_contiguous(targets);
let input_lengths = into_contiguous(input_lengths);
let target_lengths = into_contiguous(target_lengths);
let log_probs_shape = log_probs.shape();
let [_t, batch_size, _c] = log_probs_shape.dims::<3>();
let target_shape = targets.shape();
let max_target_len = target_shape.dims::<2>()[1];
let max_l_prime = 2 * max_target_len + 1;
assert!(
max_l_prime as u32 <= SHARED_ALPHA_CAPACITY,
"ctc_loss: 2 * max_target_len + 1 = {} exceeds the kernel's shared-memory \
alpha capacity ({}). Reduce target length or raise SHARED_ALPHA_CAPACITY.",
max_l_prime,
SHARED_ALPHA_CAPACITY,
);
// Pick a thread count that fits the runtime's per-cube limit. We don't
// need one thread per s position - threads stride over s.
let hw_max = log_probs.client.properties().hardware.max_cube_dim.0;
let cube_dim_x = (max_l_prime as u32).min(hw_max).min(256);
let client = log_probs.client.clone();
let device = log_probs.device.clone();
let f_dtype = log_probs.dtype;
let i_dtype = targets.dtype;
let output = empty_device_dtype(client.clone(), device, Shape::new([batch_size]), f_dtype);
let cube_count = CubeCount::Static(batch_size as u32, 1, 1);
let cube_dim = CubeDim::new_1d(cube_dim_x);
View on GitHub (pinned to d16f7ba2ed)
Solutions
- Load the record on the inner policy BEFORE constructing the AsyncPolicy: build the base policy, call policy.load_record(record), then wrap it with AsyncPolicy::new.
- Refactor the caller to keep a handle to the inner policy so record loading never goes through the async wrapper.
- If you need post-hoc state updates, file/upstream an issue; the only in-library path is the pre-load pattern.
Example fix
// before let policy = AsyncPolicy::new(base_policy); let policy = policy.load_record(record); // panics: unimplemented! // after let policy = base_policy.load_record(record); let policy = AsyncPolicy::new(policy);
Defensive patterns
Strategy: validation
Validate before calling
fn load_record_safe<P: Policy>(policy: &P, record: &P::Record) -> Result<(), &'static str> {
if std::any::TypeId::of::<P>() == std::any::TypeId::of::<crate::policy::AsyncPolicy<()>>() {
return Err("load_record is unimplemented on AsyncPolicy; load on the inner policy first");
}
Ok(())
} Type guard
fn is_async_policy_marker(msg: &str) -> bool {
msg.contains("load the record on the inner policy")
} Try / catch
// Rust panics are not catchable idiomatically; guard by construction: let inner = base_policy.load_record(record); let policy = AsyncPolicy::new(inner);
Prevention
- Always restore records on the base policy before wrapping in AsyncPolicy.
- Keep a reference to the inner policy alongside the AsyncPolicy for checkpoint ops.
- Grep your code for `.load_record(` calls reachable from generic `Policy` trait objects.
- Add a debug_assert or unit test that exercises your restore path.
When it happens
Trigger: Calling load_record on an AsyncPolicy (e.g. when restoring a checkpointed policy from a saved record through a generic Policy trait object that happens to be an AsyncPolicy).
Common situations: Checkpoint restore/finetuning workflows where code is polymorphic over Policy and does not special-case AsyncPolicy; serializing a training run and resuming with the policy already wrapped for async inference.
Related errors
- ctc_loss_backward: 2 * max_target_len + 1 = {} exceeds the k
- Node {:?} is needed but never checkpointed
- Trying to consume the gradients for an untracked tensor
- Invalid broadcast shapes: Next grad shape {:?}, Previous gra
- Can't differentiate embedding backward.
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/2d90c97bb9ee521c.
Report an issue: GitHub.