jax-ml/jax · error · TypeError

No constant handler for type: {type(val)}

Error message

No constant handler for type: {type(val)}

What it means

Raised by JAX's MLIR lowering machinery when a Python object passed as a constant to a jitted function has no registered constant handler for its type. During tracing/lowering, every concrete value must be converted into an MLIR constant; only types with registered handlers (numpy arrays/scalars, Python scalars, etc.) or objects exposing __jax_array__ can be lowered. Any other type (e.g. a custom class, torch tensor, dict, string in an unexpected path) reaches the fallback and triggers this TypeError.

Source

Thrown at jax/_src/interpreters/mlir.py:327

def _ir_constant(val: Any, *,
  const_lowering: dict[tuple[int, core.AbstractValue], IrValues] | None = None,
  aval: core.AbstractValue | None = None
) -> IrValues:
  if const_lowering is not None:
    # pyrefly: ignore[bad-argument-type]
    if np.shape(val) and (c_val := const_lowering.get((id(val), aval))) is not None:
      return c_val
  for t in type(val).__mro__:
    handler = _constant_handlers.get(t)
    if handler:
      out = handler(val, aval)
      assert _is_ir_values(out), (type(val), out)
      return out
  m = getattr(val, '__jax_array__', None)
  if m is not None:
    return ir_constant(m())
  raise TypeError(f"No constant handler for type: {type(val)}")


def _numpy_array_constant(x: np.ndarray | np.generic) -> ir.Value:
  return hlo.constant(_numpy_array_attribute(x))


def _masked_array_constant_handler(*args, **kwargs):
  raise ValueError("numpy masked arrays are not supported as direct inputs to JAX functions. "
                   "Use arr.filled() to convert the value to a standard numpy array.")

register_constant_handler(np.ma.MaskedArray, _masked_array_constant_handler)

def _shape_dtype_struct_constant_handler(*args, **kwargs):
  raise TypeError("A ShapeDtypeStruct does not have a value and cannot be "
                  "used as a constant in a JAX function.")

register_constant_handler(core.ShapeDtypeStruct,
                          _shape_dtype_struct_constant_handler)

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Convert the value to a numpy array or JAX array (jnp.asarray / np.asarray) before passing it
  2. If it is a custom object, implement __jax_array__ returning a jnp array, or restructure to pass plain arrays
  3. Move non-array configuration objects into static_argnums/static_argnames so they are treated as Python constants, not traced values
  4. Register a constant handler with register_constant_handler if you control the type

Example fix

// before
f = jax.jit(lambda x, cfg: x * cfg.scale)
f(jnp.ones(3), MyConfig(scale=2))  # TypeError: No constant handler

// after
f = jax.jit(lambda x, scale: x * scale, static_argnames=('scale',))
f(jnp.ones(3), 2)
Defensive patterns

Strategy: type-guard

Validate before calling

def is_lowerable_const(v):
    return hasattr(v, '__jax_array__') or isinstance(v, (np.ndarray, np.generic, bool, int, float, complex))

args = [a for a in args if not isinstance(a, (str, dict))]

Type guard

def is_jax_constant(v) -> bool:
    return hasattr(v, '__jax_array__') or isinstance(
        v, (np.ndarray, np.generic, bool, int, float, complex))

Try / catch

try:
    out = jitted_fn(x)
except TypeError as e:
    if 'No constant handler' in str(e):
        x = np.asarray(x)  # or move to static args
        out = jitted_fn(x)
    else:
        raise

Prevention

When it happens

Trigger: Passing an object of an unregistered type as a static/constant argument to jit/pmap/scan/pmap-style lowering, e.g. a custom Python class, a non-JAX array (torch.Tensor, pandas object), or a dict where a scalar is expected; also when a user-defined aval/ShapeDtypeStruct-like object is fed as a value.

Common situations: Mixing JAX with other frameworks (passing a torch tensor directly), passing custom dataclass instances into jitted code, stale registrations after upgrading JAX where a handler moved, or passing nested containers holding unsupported leaves.

Related errors


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