jax-ml/jax · error · ValueError
expn does not support complex-valued inputs.
Error message
expn does not support complex-valued inputs.
What it means
jax.scipy.special.expn (generalized exponential integral En) rejects complex x after promotion via promote_args_inexact. Its piecewise branch structure (small-x series vs continued fraction) is implemented only for real floats.
Source
Thrown at jax/_src/scipy/special.py:2965
.. math::
\mathrm{expn}(n, x) = E_n(x) = x^{n-1}\int_x^\infty\frac{e^{-t}}{t^n}\mathrm{d}t
Args:
n: arraylike, real-valued
x: arraylike, real-valued
Returns:
array of expn values
See also:
- :func:`jax.scipy.special.expi`
- :func:`jax.scipy.special.exp1`
"""
n, x = promote_args_inexact("expn", n, x)
if dtypes.issubdtype(x.dtype, np.complexfloating):
raise ValueError("expn does not support complex-valued inputs.")
_c = _lax_const
zero = _c(x, 0)
one = _c(x, 1)
conds = [
(n < _c(n, 0)) | (x < zero),
(x == zero) & (n < _c(n, 2)),
(x == zero) & (n >= _c(n, 2)),
(n == _c(n, 0)) & (x >= zero),
(n >= _c(n, 5000)),
(x > one),
]
n1 = jnp.where(n == _c(n, 1), n + n, n)
vals = [
np.nan,
np.inf,
one / n1, # prevent div by zero
jnp.exp(-x) / x,
_expn3,View on GitHub (pinned to 1e1c6a8fc0)
Solutions
- For E1 of complex argument use mpmath.e1 or scipy on the host via jax.pure_callback.
- For real pipelines, ensure upstream ops (fft, casts) have not promoted x to complex (e.g. use jnp.real(x) if imaginary parts are numerically zero).
- Check x.dtype in debug runs to find where the promotion to complex happens.
Example fix
# before (raises)
y = jax.scipy.special.expn(2, x) # x complex
# after: strip spurious imaginary part or use host SciPy
y = jax.scipy.special.expn(2, jnp.real(x)) if jnp.allclose(x.imag, 0) else \
jax.pure_callback(lambda v: scipy.special.expn(2, v), x.real.dtype, x) Defensive patterns
Strategy: type-guard
Validate before calling
x = jnp.asarray(x)
if dtypes.issubdtype(x.dtype, jnp.complexfloating):
if jnp.allclose(x.imag, 0):
x = x.real
else:
raise TypeError('expn is real-only in JAX') Type guard
def coerce_real_if_imaginary_zero(x):
x = jnp.asarray(x)
if dtypes.issubdtype(x.dtype, jnp.complexfloating) and np.allclose(x.imag, 0):
return x.real
return x Try / catch
try:
y = jax.scipy.special.expn(n, x)
except ValueError:
y = jax.pure_callback(lambda a: scipy.special.expn(n, a), x.real.dtype, x) Prevention
- Trace dtype promotion in pipelines that mix fft with special functions.
- Centralize expn/exp1/expi calls in one module with dtype guards.
When it happens
Trigger: Calling jax.scipy.special.expn(n, x) with complex x; transitively, any complex input to exp1 (which calls expn(1, x)) also raises here.
Common situations: Complex-argument E_n integrals in physics code; passing complex values to exp1 expecting SciPy semantics where scipy.special.expn supports complex inputs.
Related errors
- exp1 does not support complex-valued inputs.
- expi does not support complex-valued inputs.
- Argument `x` to sici must be real-valued. Got dtype {x.dtype
- Value of type {type(self)} is not convertible to complex.
- top_k is not compatible with complex inputs.
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/bcbf6fe062cf1400.
Report an issue: GitHub.