tracel-ai/burn · error

Cross product requires dimension {} to have size 3, but got

Error message

Cross product requires dimension {} to have size 3, but got {} and {}

What it means

The cross-product kernel requires the operand dimension `dim` to have exactly size 3 on both inputs (a cross product is only defined for 3-vectors). The kernel validates this on the host before launch and panics otherwise.

Source

Thrown at crates/burn-cubecl/src/kernel/cross.rs:52

    let b2 = rhs.read(base_pos + 2);

    // Compute cross product: a × b
    let x = a1 * b2 - a2 * b1;
    let y = a2 * b0 - a0 * b2;
    let z = a0 * b1 - a1 * b0;

    // Store result
    output.write(base_pos, x);
    output.write(base_pos + 1, y);
    output.write(base_pos + 2, z);
}

pub(crate) fn cross(lhs: CubeTensor, rhs: CubeTensor, dim: usize) -> CubeTensor {
    let ndims = lhs.meta.num_dims();

    // Validate that the cross dimension has size 3
    if lhs.meta.shape()[dim] != 3 || rhs.meta.shape()[dim] != 3 {
        panic!(
            "Cross product requires dimension {} to have size 3, but got {} and {}",
            dim,
            lhs.meta.shape()[dim],
            rhs.meta.shape()[dim]
        );
    }

    // The kernel reads each 3-vector from contiguous memory, so it expects the
    // cross dimension to be the last (innermost) and physically contiguous.
    // For non-last dims we permute the cross dim to the last position, run the
    // kernel, then permute the result back. swap_dims only updates strides, so
    // make the permuted operands contiguous before launch.
    if dim != ndims - 1 {
        let last = ndims - 1;
        let lhs = into_contiguous(swap_dims(lhs, dim, last));
        let rhs = into_contiguous(swap_dims(rhs, dim, last));
        let result = cross(lhs, rhs, last);
        return swap_dims(result, dim, last);

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Slice/squeeze the tensors so the cross dimension has exactly 3 elements
  2. Pass the correct `dim` index (the one with size 3)
  3. For 4-component vectors, drop the padding component (e.g. xyzw -> xyz) before crossing
  4. Check both tensors have the same rank and the target dim exists in both

Example fix

// before
tensor.cross(other, -1) // dim has size 4
// after
let a = tensor.slice_dim(-1, 0..3);
let b = other.slice_dim(-1, 0..3);
a.cross(b, tensor.dims().len() - 1);
Defensive patterns

Strategy: validation

Validate before calling

assert_eq!(tensor.shape()[dim], 3, "cross dim must be size 3");
assert_eq!(other.shape()[dim], 3, "cross dim must be size 3");

Type guard

fn can_cross(a: &TensorBase, b: &TensorBase, dim: usize) -> bool {
    a.shape().get(dim) == Some(&3) && b.shape().get(dim) == Some(&3)
}

Prevention

When it happens

Trigger: Calling `tensor.cross(other, dim)` (burn cross op) where `lhs.shape()[dim] != 3` or `rhs.shape()[dim] != 3`, or where `dim` is out of bounds for one tensor.

Common situations: Accidentally passing the batch dimension instead of the vector dimension; tensors with trailing vector size other than 3 (e.g. 2D vectors or padded 4-vectors); mismatched tensors of different ranks.

Related errors


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