jax-ml/jax · error · ValueError

exp1 does not support complex-valued inputs.

Error message

exp1 does not support complex-valued inputs.

What it means

jax.scipy.special.exp1 (exponential integral E1) immediately delegates to expn(1, x) and inherits its restriction: complex inputs raise ValueError. Although E1 has a standard complex definition (Ei/E1 via analytic continuation), JAX's implementation is real-only.

Source

Thrown at jax/_src/scipy/special.py:3022

  .. math::

     \mathrm{exp1}(x) = E_1(x) = \int_x^\infty\frac{e^{-t}}{t}\mathrm{d}t


  Args:
    x: arraylike, real-valued

  Returns:
    array of exp1 values

  See also:
    - :func:`jax.scipy.special.expi`
    - :func:`jax.scipy.special.expn`
  """
  x, = promote_args_inexact("exp1", x)
  if dtypes.issubdtype(x.dtype, np.complexfloating):
    raise ValueError("exp1 does not support complex-valued inputs.")
  return expn(1, x)


def _spence_poly(w: Array) -> Array:
  A = jnp.array([4.65128586073990045278E-5,
                  7.31589045238094711071E-3,
                  1.33847639578309018650E-1,
                  8.79691311754530315341E-1,
                  2.71149851196553469920E0,
                  4.25697156008121755724E0,
                  3.29771340985225106936E0,
                  1.00000000000000000126E0,
                  ], dtype=w.dtype)

  B = jnp.array([6.90990488912553276999E-4,
                  2.54043763932544379113E-2,
                  2.82974860602568089943E-1,
                  1.41172597751831069617E0,

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Use scipy.special.exp1 or mpmath.expint via jax.pure_callback for complex arguments.
  2. If the imaginary part is a numerical artifact, take jnp.real(x) after verifying it is ~0.
  3. Add a dtype assertion in your wrapper to fail fast with a clearer message.

Example fix

# before (raises)
y = jax.scipy.special.exp1(z)  # z complex

# after
y = jax.pure_callback(scipy.special.exp1, z.real.dtype, z)
Defensive patterns

Strategy: type-guard

Validate before calling

x = jnp.asarray(x)
if dtypes.issubdtype(x.dtype, jnp.complexfloating):
    raise TypeError('exp1 in JAX is real-only; use scipy.special.exp1 for complex x')

Type guard

def is_real_float(x) -> bool:
    return not dtypes.issubdtype(jnp.asarray(x).dtype, jnp.complexfloating)

Try / catch

try:
    y = jax.scipy.special.exp1(x)
except ValueError:
    y = jax.pure_callback(scipy.special.exp1, x.real.dtype, x)

Prevention

When it happens

Trigger: Passing complex arrays or Python complex numbers to jax.scipy.special.exp1; complex tangents under jit/grad flows that reach exp1.

Common situations: Porting SciPy/mpmath code computing E1 for complex arguments (e.g. plasma dispersion, Laplace-transform inversion); accidental complex promotion from previous ops.

Related errors


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