jax-ml/jax · error · TypeError

Value of type {type(self)} is not convertible to complex.

Error message

Value of type {type(self)} is not convertible to complex.

What it means

Raised by JAXTracer.__complex__ when Python tries to convert a JAX Tracer to a complex scalar (complex(x)). Tracers are symbolic values created during tracing by jit/grad/vmap/etc. and have no concrete numeric value, so conversion to a Python complex number is disallowed. JAX throws this TypeError rather than producing an incorrect result.

Source

Thrown at jax/_src/core.py:1129

    return self.aval._bool(self)

  def __int__(self):
    if is_concrete(self): return int(self.to_concrete_value())
    check_scalar_conversion(self)
    if not hasattr(self.aval, "_int"):
      raise TypeError(f"Value of type {type(self)} is not convertible to integer.")
    return self.aval._int(self)

  def __float__(self):
    check_scalar_conversion(self)
    if not hasattr(self.aval, "_float"):
      raise TypeError(f"Value of type {type(self)} is not convertible to float.")
    return self.aval._float(self)

  def __complex__(self):
    check_scalar_conversion(self)
    if not hasattr(self.aval, "_complex"):
      raise TypeError(f"Value of type {type(self)} is not convertible to complex.")
    return self.aval._complex(self)

  def __hex__(self):
    if is_concrete(self): return hex(self.to_concrete_value())
    check_integer_conversion(self)
    if not hasattr(self.aval, "_hex"):
      raise TypeError(f"Value of type {type(self)} is not convertible to hex.")
    return self.aval._hex(self)

  def __oct__(self):
    if is_concrete(self): return oct(self.to_concrete_value())
    check_integer_conversion(self)
    if not hasattr(self.aval, "_oct"):
      raise TypeError(f"Value of type {type(self)} is not convertible to oct.")
    return self.aval._oct(self)

  def __index__(self):
    if is_concrete(self): return operator.index(self.to_concrete_value())

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Keep the arithmetic in JAX: use jax.numpy.complex64/complex128 dtypes or construct via x + 1j*y instead of complex(x, y) on host scalars.
  2. If a concrete complex value is genuinely needed, compute it outside the traced function and pass it in as a static/closed-over Python scalar.
  3. Replace cmath calls with jax.lax.complex / jax.numpy equivalents.
  4. For debugging, use jax.debug.print instead of host-side conversion.

Example fix

# before
@jax.jit
def f(re, im):
    z = complex(re, im)   # TypeError: Tracer not convertible to complex
    return jnp.abs(z)

# after
@jax.jit
def f(re, im):
    z = re + 1j * im      # stays a JAX value
    return jnp.abs(z)
Defensive patterns

Strategy: type-guard

Validate before calling

import jax
def safe_complex(x, y):
    if isinstance(x, jax.core.Tracer) or isinstance(y, jax.core.Tracer):
        return x + 1j * y  # stay symbolic
    return complex(x, y)

Type guard

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

Prevention

When it happens

Trigger: Calling complex(tracer) or numpy.complex128(tracer) inside a jitted/grad-traced function; passing a traced value to cmath functions or code that does implicit complex conversion; constructing complex literals like complex(0, x) from traced parts.

Common situations: Writing signal-processing or quantum simulation loss functions under jax.grad that build complex numbers from traced parameters; interop code that normalizes inputs with complex(); NumPy code reused inside jax.jit without adaptation.

Related errors


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