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
- Convert the value to a numpy array or JAX array (jnp.asarray / np.asarray) before passing it
- If it is a custom object, implement __jax_array__ returning a jnp array, or restructure to pass plain arrays
- Move non-array configuration objects into static_argnums/static_argnames so they are treated as Python constants, not traced values
- 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
- Convert all inputs with jnp.asarray before calling jitted functions
- Pass configuration objects via static_argnames, never as traced values
- Never feed tensors from other frameworks directly into JAX
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
- Cannot interpret value of type {typ} as an abstract array; i
- function {dbg.func_src_info} traced for {dbg.traced_for} ret
- The kernel function in the pallas_call {debug_info.func_src_
- {name} was requested to map a value of non-array type {core.
- primal and tangent arguments to jax.jvp must be tuples or li
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/75450f8a1856fa82.
Report an issue: GitHub.