jax-ml/jax · error · ValueError
Can't bitcast {x.type} (of bitwidth {x_bw}) to {new_type} (o
Error message
Can't bitcast {x.type} (of bitwidth {x_bw}) to {new_type} (of bitwidth {new_bw}) What it means
bitcast only reinterprets bits, so the total bitwidth must be preserved. This check compares the source bitwidth (including whole vectors) to the target's; a size change cannot be a bitcast and must go through a cast/extension/truncation op instead.
Source
Thrown at jax/experimental/mosaic/gpu/utils.py:2066
raise ValueError(f"Types must match, got {high.type} and {low.type}")
if high.type != i32:
high = bitcast(high, i32)
if low.type != i32:
low = bitcast(low, i32)
if permutation.type != i32:
permutation = bitcast(permutation, i32)
result = llvm.inline_asm(
i32, [high, low, permutation], "prmt.b32 $0, $1, $2, $3;", "=r,r,r,r"
)
assert isinstance(result, ir.Value)
return bitcast(result, result_type)
def bitcast(x: ir.Value, new_type: ir.Type):
if x.type == new_type:
return x
if (x_bw := bitwidth(x.type)) != (new_bw := bitwidth(new_type)):
raise ValueError(
f"Can't bitcast {x.type} (of bitwidth {x_bw}) to {new_type} (of"
f" bitwidth {new_bw})"
)
if isinstance(x.type, ir.VectorType) and isinstance(new_type, ir.IntegerType):
new_type = ir.IntegerType(new_type)
x_ty = ir.VectorType(x.type)
assert new_type.width == bitwidth(x_ty.element_type) * math.prod(x_ty.shape)
return vector.extract(
vector.bitcast(ir.VectorType.get((1,), new_type), x),
dynamic_position=[],
static_position=ir.DenseI64ArrayAttr.get([0]),
)
if isinstance(x.type, ir.IntegerType) and isinstance(new_type, ir.VectorType):
new_type = ir.VectorType(new_type)
x_ty = ir.IntegerType(x.type)
assert x_ty.width == bitwidth(new_type.element_type) * math.prod(
new_type.shape
)View on GitHub (pinned to 1e1c6a8fc0)
Solutions
- Use a real cast: arith.trunci/extsi/extui for integers, arith.extf/truncf for floats
- If packing/unpacking vectors, make the total bitwidth match exactly (e.g. vector<2xbf16> <-> i32)
- For unequal widths, first cast to the same width then bitcast
Example fix
# before x_i8 = bitcast(x_f32, ir.IntegerType.get_signless(8)) # 32 -> 8 bits # after x_i32 = bitcast(x_f32, ir.IntegerType.get_signless(32)) x_i8 = arith.trunci(ir.IntegerType.get_signless(8), x_i32)
Defensive patterns
Strategy: type-guard
Validate before calling
assert bitwidth(x.type) == bitwidth(new_type), 'bitcast must preserve total bitwidth'
Type guard
def can_bitcast(src_ty, dst_ty) -> bool:
return bitwidth(src_ty) == bitwidth(dst_ty) Prevention
- Use arith casts for width changes; reserve bitcast for same-width reinterprets
- Compute target element counts from bitwidth math when packing
When it happens
Trigger: Calling bitcast(x, new_type) where bitwidths differ, e.g. bitcasting vector<4xf32> (128 bits) to i64 (64 bits), or f32 to i8.
Common situations: Assuming bitcast can widen/narrow like reinterpret-with-resize; converting bf16x2 packing by bitcasting vector<2xbf16> to f32 (works) but to f16 (fails); mixing up truncation with reinterpreting.
Related errors
- Data type bitcast is only supported from i8 to other types.
- Only workgroup memory is supported but got {ref}.
- Data type bitcast is only supported for contiguous 1D arrays
- Can not bitcast memory region of size {shape_bitwidth} bits
- Only byte-aligned bitcasts are supported.
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/eb987ab276c17653.
Report an issue: GitHub.