tracel-ai/burn · error

cat: unsupported dtype {:?}

Error message

cat: unsupported dtype {:?}

What it means

cat in burn-flex dispatches concat on the dtype of the input tensors, instantiating cat_impl for every numeric type plus a special arm mapping U8 and Bool onto u8 storage. Any other dtype combination reaches the catch-all and panics. All tensors in the list must share the dtype — the dtype is taken from tensors[0].

Source

Thrown at crates/burn-flex/src/ops/cat.rs:30

    if tensors.len() == 1 {
        return tensors.into_iter().next().unwrap();
    }

    let dtype = tensors[0].dtype();
    match dtype {
        DType::F32 => cat_impl::<f32>(tensors, dim),
        DType::F64 => cat_impl::<f64>(tensors, dim),
        DType::F16 => cat_impl::<f16>(tensors, dim),
        DType::BF16 => cat_impl::<bf16>(tensors, dim),
        DType::I64 => cat_impl::<i64>(tensors, dim),
        DType::I32 => cat_impl::<i32>(tensors, dim),
        DType::I16 => cat_impl::<i16>(tensors, dim),
        DType::I8 => cat_impl::<i8>(tensors, dim),
        DType::U64 => cat_impl::<u64>(tensors, dim),
        DType::U32 => cat_impl::<u32>(tensors, dim),
        DType::U16 => cat_impl::<u16>(tensors, dim),
        DType::U8 | DType::Bool(_) => cat_impl::<u8>(tensors, dim),
        _ => panic!("cat: unsupported dtype {:?}", dtype),
    }
}

fn cat_impl<E: Element + bytemuck::Pod>(tensors: Vec<FlexTensor>, dim: usize) -> FlexTensor {
    let dtype = tensors[0].dtype();
    let first_shape = tensors[0].layout().shape();
    let ndims = first_shape.num_dims();

    assert!(
        dim < ndims,
        "cat: dim {} out of bounds for {} dimensions",
        dim,
        ndims
    );

    // Compute output shape: sum along cat dim, others must match
    let mut out_dims = first_shape.to_vec();
    out_dims[dim] = 0;

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Cast all tensors to a common supported dtype before cat: tensors.iter().map(|t| t.cast(DType::F32)).collect().
  2. Ensure tensors[0] has a supported dtype since the dispatch keys off it.
  3. Normalize bool tensors explicitly (bool_empty/bool_into_int helpers) rather than relying on the U8|Bool arm.

Example fix

// before
let out = cat(vec![a, b_f32], 0); // a is i64, b f32
// after
let out = cat(vec![a.cast(DType::F32), b_f32], 0);
Defensive patterns

Strategy: validation

Validate before calling

let dtype = tensors[0].dtype();
if !matches!(dtype, DType::F64 | DType::F32 | DType::F16 | DType::BF16 | DType::I64 | DType::I32 | DType::I16 | DType::I8 | DType::U64 | DType::U32 | DType::U16 | DType::U8 | DType::Bool(_)) {
    tensors = tensors.into_iter().map(|t| t.cast(DType::F32)).collect();
}
let out = cat(tensors, dim);

Type guard

fn all_same_supported_dtype(ts: &[FlexTensor]) -> bool {
    let d = ts[0].dtype();
    ts.iter().all(|t| t.dtype() == d)
}

Try / catch

let out = std::panic::catch_unwind(|| cat(tensors.clone(), dim))
    .unwrap_or_else(|_| cat(tensors.iter().map(|t| t.cast(DType::F32)).collect(), dim));

Prevention

When it happens

Trigger: Concatenating tensors whose dtype is not one of the listed numeric types, or where the first tensor's dtype is unsupported (dtype is read from tensors[0]). Mismatched dtypes across the list can also misroute into the wrong typed cat_impl.

Common situations: Concatenating bool masks with u8 buffers where an exotic dtype alias slipped in; mixed float/int lists relying on promotion; empty or mismatched tensor lists after filtering.

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/0e8fa3b5204da992. Report an issue: GitHub.