jax-ml/jax · error · ValueError

Passing complex start/stop/step to jnp.arange is no longer s

Error message

Passing complex start/stop/step to jnp.arange is no longer supported starting in JAX v0.10.0.

What it means

Starting with JAX v0.10.0, complex-valued start/stop/step arguments to jnp.arange are rejected with this ValueError. Complex arange has ambiguous semantics and poor hardware support, so JAX removed it; users must construct complex ranges manually from real ones.

Source

Thrown at jax/_src/numpy/lax_numpy.py:5971

  # Ensure start/stop/step are scalars
  for name, val in [(start_name, start), ("stop", stop), ("step", step)]:
    if val is not None and np.ndim(val) != 0:
      raise ValueError(f"jax.numpy.arange: arguments must be scalars; got {name}={val}")

  # Handle symbolic dimensions
  if any(core.is_symbolic_dim(v) for v in (start, stop, step)):
    if stop is None:
      start, stop = 0, start
    if step is None:
      step = 1
    return _arange_dynamic(start, stop, step, dtype or dtypes.default_int_dtype())

  if dtype is None:
    dtype = dtypes.result_type(start, *(x for x in [stop, step] if x is not None))
  dtype = dtypes.jax_dtype(dtype)

  if iscomplexobj(start) or iscomplexobj(stop) or iscomplexobj(step):
    raise ValueError(
        "Passing complex start/stop/step to jnp.arange is no longer supported"
        " starting in JAX v0.10.0.")

  if stop is None:
    start, stop = 0, start

  if step is not None:
    # arange(N, M, K)
    if (dtype is not None and
        dtypes.issubdtype(dtype, np.floating) and
        dtypes.finfo(dtype).bits < 32):
      working_dtype = np.dtype('float32')
    else:
      working_dtype = dtype
    size = max(0, int(np.ceil((stop - start) / step)))
    return lax.convert_element_type(
        lax.add(lax.convert_element_type(start, working_dtype),
                lax.mul(lax.convert_element_type(step, working_dtype),

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Build a real arange and convert: (jnp.arange(n) * step).astype(complex) or jnp.arange(n) * (1+2j)
  2. Use jnp.linspace for complex endpoints: jnp.linspace(0, 5+0j, n) which supports complex dtypes
  3. Generate complex values via explicit real+imag construction

Example fix

// before
z = jnp.arange(0, 10, 1+0.5j)
// after
z = jnp.arange(0, 10) * (1+0.5j)
Defensive patterns

Strategy: validation

Validate before calling

import jax.numpy as jnp
assert not jnp.iscomplexobj(start) and not jnp.iscomplexobj(stop) and not jnp.iscomplexobj(step)

Type guard

def is_real_scalar(v) -> bool:
    return np.ndim(v) == 0 and not np.iscomplexobj(v)

Prevention

When it happens

Trigger: jnp.arange(0, 5, 1+2j), or passing complex-typed start/stop computed from complex dtype promotions, e.g. arange over a complex endpoint after result_type of a complex array.

Common situations: Upgrading JAX past v0.10.0 breaks previously-working (or silently odd) complex arange calls; complex-valued signal generation code (phasors, complex exponent grids) that used arange directly.

Related errors


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