jax-ml/jax · error · TracerBoolConversionError

TracerBoolConversionError

Error message

TracerBoolConversionError

What it means

TracerBoolConversionError is raised when Python bool() is applied to a Tracer, e.g. 'if tracer_value:' inside a jitted function. Branching on a traced value is impossible because its value is not known at trace time.

Source

Thrown at jax/_src/core.py:2038

def is_concrete(x):
  return to_concrete_value(x) is not None

def to_concrete_value(x):
  if isinstance(x, Tracer):
    return x.to_concrete_value()
  else:
    return x

def concretization_function_error(fun, suggest_astype=False):
  fname = getattr(fun, "__name__", fun)
  fname_context = f"The problem arose with the `{fname}` function. "
  if suggest_astype:
    fname_context += ("If trying to convert the data type of a value, "
                      f"try using `x.astype({fun.__name__})` "
                      f"or `jnp.array(x, {fun.__name__})` instead.")
  if fun is bool:
    def error(self, arg):
      raise TracerBoolConversionError(arg)
  elif fun in (hex, oct, operator.index):
    def error(self, arg):
      raise TracerIntegerConversionError(arg)
  else:
    def error(self, arg):
      raise ConcretizationTypeError(arg, fname_context)
  return error

def concrete_or_error(force: Any, val: Any, context=""):
  """Like force(val), but gives the context in the error message."""
  if force is None:
    force = lambda x: x
  if isinstance(val, Tracer):
    maybe_concrete = val.to_concrete_value()
    if maybe_concrete is None:
      raise ConcretizationTypeError(val, context)
    else:
      return force(maybe_concrete)

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Use jax.lax.cond / lax.switch for data-dependent branching
  2. Compute the condition outside the jit and pass it as a static value or use two jitted branches
  3. For scalar debugging checks, print the value after the call, or use jax.debug.print
  4. Guard assertions outside traced functions or use static_argnums

Example fix

# before
@jax.jit
def f(x):
    if x > 0:
        return x
    return -x

# after
@jax.jit
def f(x):
    return jax.lax.cond(x > 0, x, lambda v: v, x, lambda v: -v)
Defensive patterns

Strategy: type-guard

Validate before calling

import jax
def guard_branch(x):
    assert not isinstance(x, jax.core.Tracer), 'branch on concrete value outside jit'

Type guard

def is_tracer(x) -> bool:
    import jax; return isinstance(x, jax.core.Tracer)

Prevention

When it happens

Trigger: Using a Tracer in an if statement, while condition, assert, any()/all() over tracers, or bare 'if x:' inside jax.jit/grad/vmap; also bool(x) or placing a tracer in a boolean context.

Common situations: Writing control flow that depends on data (early stopping, NaN checks like 'if jnp.isnan(x):') inside @jax.jit; using Python any/all on traced booleans.

Related errors


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