{"record":{"id":"ff24c317333b83b5","repo":"jax-ml/jax","slug":"cannot-bitcast-from-x-dtype-old-bitwidth-bits","errorCode":null,"errorMessage":"Cannot bitcast from {x.dtype} ({old_bitwidth} bits) to {dtype} ({new_bitwidth} bits), because {x.shape[-1]=} * {old_bitwidth} is not divisible by {new_bitwidth}","messagePattern":"Cannot bitcast from (.+?) \\((.+?) bits\\) to (.+?) \\((.+?) bits\\), because (.+?) \\* (.+?) is not divisible by (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/pallas/mosaic/sc_primitives.py","lineNumber":448,"sourceCode":"\n\nbitcast_p = jax_core.Primitive(\"bitcast\")\n\n\n@bitcast_p.def_abstract_eval\ndef _bitcast_abstract_eval(x, dtype):\n  old_bitwidth = dtypes.itemsize_bits(x.dtype)\n  new_bitwidth = dtypes.itemsize_bits(dtype)\n  if old_bitwidth == new_bitwidth:\n    return jax_core.ShapedArray(x.shape, dtype)\n  if x.ndim == 0:\n    raise ValueError(\n        \"Cannot bitcast a ()-shaped array to a dtype with a different bitwidth:\"\n        f\" {old_bitwidth=} vs {new_bitwidth=}\"\n    )\n  new_last_dim, rem = divmod(x.shape[-1] * old_bitwidth, new_bitwidth)\n  if rem:\n    raise ValueError(\n        f\"Cannot bitcast from {x.dtype} ({old_bitwidth} bits) to\"\n        f\" {dtype} ({new_bitwidth} bits), because {x.shape[-1]=} *\"\n        f\" {old_bitwidth} is not divisible by {new_bitwidth}\"\n    )\n  return jax_core.ShapedArray((*x.shape[:-1], new_last_dim), dtype)\n\n\n@sc_lowering.register_lowering_rule(bitcast_p)\ndef _bitcast_lowering_rule(ctx: sc_lowering.LoweringRuleContext, x, *, dtype):\n  del dtype  # Unused.\n  [out_aval] = ctx.avals_out\n  return vector.bitcast(ctx.aval_to_ir_type(out_aval), x)\n\n\ndef bitcast(x: jax.Array, dtype: jax.typing.DTypeLike) -> jax.Array:\n  \"\"\"Bitcasts an array to a different dtype.\n\n  Unlike ``lax.bitcast_convert_type``, this function returns an array of the","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/pallas/mosaic/sc_primitives.py#L430-L466","documentation":"For non-scalar arrays, bitcasting to a different bitwidth requires the last dimension's total bits (shape[-1] * old_bitwidth) to be divisible by the new bitwidth. If not, the bits cannot be repacked into whole elements of the new dtype.","triggerScenarios":"e.g. bitcast of a float32 array with last dim 3 to int32 (3*32/32 ok) vs last dim 3 to bfloat16 from int8 where 3*8=24 not divisible by 16; any last-dim size where the bit count doesn't divide evenly.","commonSituations":"Viewing buffers as a different-width dtype (u8->f16, f32->2xbf16) with a trailing dimension that isn't a multiple of the width ratio.","solutions":["Pad or slice the last dimension so shape[-1]*old_bits is divisible by new_bits (e.g. make last dim even for 8->16 bit casts)","Choose a target dtype whose bitwidth divides the row's total bits","Verify the last-dim size matches the ratio new_bitwidth//gcd(old,new)"],"exampleFix":"// before\ny = bitcast(x_u8, jnp.uint16)  # x.shape[-1]=3 -> 24 bits not divisible by 16\n\n// after\nx = jnp.pad(x_u8, [(0,0),(0,1)])  # last dim 4\ny = bitcast(x, jnp.uint16)","handlingStrategy":"validation","validationCode":"ob, nb = dtypes.itemsize_bits(x.dtype), dtypes.itemsize_bits(dtype)\nif ob != nb and (x.shape[-1] * ob) % nb:\n    pad = (-x.shape[-1]) % (nb // math.gcd(ob, nb))\n    x = jnp.pad(x, [(0, 0)] * (x.ndim - 1) + [(0, pad)])","typeGuard":"def bitcast_ok(x, dtype) -> bool:\n    ob, nb = dtypes.itemsize_bits(x.dtype), dtypes.itemsize_bits(dtype)\n    return ob == nb or (x.ndim > 0 and (x.shape[-1] * ob) % nb == 0)","tryCatchPattern":null,"preventionTips":["Make trailing dims multiples of the bitwidth ratio before viewing","Add a shape assertion helper before buffer reinterpretation","Unit-test bitcast paths with odd trailing sizes"],"tags":["jax","pallas","sparsecore","bitcast","divisibility"],"backgroundTag":"invalid-bitcast-shape","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}