jax-ml/jax · error · ValueError

When changing to a larger dtype, its size must be a divisor

Error message

When changing to a larger dtype, its size must be a divisor of the total size in bytes of the last axis of the array.

What it means

When viewing an array as a dtype with a different itemsize, the last axis's total size in bits must be divisible by the new itemsize so elements map cleanly. This mirrors NumPy's rule for larger dtypes: the last axis must be divisible in bytes by the new itemsize.

Source

Thrown at jax/_src/numpy/array_methods.py:607

  """
  if type is not None:
    raise NotImplementedError("`type` argument of array.view() is not supported.")

  if dtype is None:
    return self

  dtype = dtypes.check_and_canonicalize_user_dtype(dtype, "view")

  nbits_in = dtypes.itemsize_bits(self.dtype)
  nbits_out = dtypes.itemsize_bits(dtype)

  if self.ndim == 0:
    if nbits_in != nbits_out:
      raise ValueError("view() of a 0d array is only supported if the itemsize is unchanged.")
    return _view(lax.expand_dims(self, (0,)), dtype).squeeze()

  if (self.shape[-1] * nbits_in) % nbits_out != 0:
    raise ValueError("When changing to a larger dtype, its size must be a divisor "
                     "of the total size in bytes of the last axis of the array.")

  if self.dtype == dtype:
    return self

  # lax.bitcast_convert_type does not support bool or complex; in these cases we
  # cast to a compatible type and recursively call _view for simplicity.
  if self.dtype == bool:
    return _view(self.astype('uint8'), dtype)

  if lax_numpy.issubdtype(self.dtype, np.complexfloating):
    new_shape = (*self.shape[:-1], self.shape[-1] * 2)
    new_dtype = lax_numpy.finfo(self.dtype).dtype
    new_sharding = core.typeof(self).sharding
    self = (array_creation.zeros(new_shape, new_dtype, out_sharding=new_sharding)
            .at[..., 0::2].set(self.real)
            .at[..., 1::2].set(self.imag))
    return _view(self, dtype)

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Pad or trim the last axis so its byte-length is divisible by the new itemsize (e.g. pad to multiple of 4 before uint8->uint32 view)
  2. View to the same-itemsize dtype first, then reshape
  3. Reshape so the last axis has a compatible length before viewing

Example fix

# before
a = jnp.zeros((3,), jnp.float32)
a.view(jnp.float64)  # 12 bytes not divisible by 8

# after
a = jnp.zeros((4,), jnp.float32)
a.view(jnp.float64)  # shape (2,)
Defensive patterns

Strategy: validation

Validate before calling

def view_dtype(a, dtype):
    from jax import dtypes
    out_bits = dtypes.itemsize_bits(dtype)
    assert (a.shape[-1] * dtypes.itemsize_bits(a.dtype)) % out_bits == 0, \
        'last axis bits not divisible by new itemsize'
    return a.view(dtype)

Prevention

When it happens

Trigger: `arr.view(dtype)` where (arr.shape[-1] * itemsize_bits(arr.dtype)) % itemsize_bits(dtype) != 0, e.g. a float32 array of shape (3,) viewed as float64 (12 bytes / 8 not integral), or shape (3,) uint8 viewed as uint32.

Common situations: Bit-reinterpreting packed feature vectors whose length doesn't align to the new type; viewing images (H, W, 3) uint8 as a wider type.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/816825ef503f28c4. Report an issue: GitHub.