jax-ml/jax · error · ValueError

nperseg must be a positive integer

Error message

nperseg must be a positive integer

What it means

nperseg (segment length for windowed FFTs) must be a concrete positive integer >= 1. Zero, negatives, or non-concrete values (e.g. traced JAX scalars) raise this error, because segmenting requires static shapes under jit.

Source

Thrown at jax/_src/scipy/signal.py:687

    # Check if we can broadcast the outer axes together
    try:
      outershape = jnp.broadcast_shapes(tuple_delete(x.shape, axis),
                                        tuple_delete(y_arr.shape, axis))
    except ValueError as err:
      raise ValueError('x and y cannot be broadcast together.') from err

  result_dtype = dtypes.to_complex_dtype(x.dtype)
  freq_dtype = np.finfo(result_dtype).dtype

  nperseg_int: int = 0
  nfft_int: int = 0
  noverlap_int: int = 0

  if nperseg is not None:  # if specified by user
    nperseg_int = core.concrete_or_error(
        int, nperseg, "nperseg of windowed-FFT")
    if nperseg_int < 1:
      raise ValueError('nperseg must be a positive integer')
  # parse window; if array like, then set nperseg = win.shape
  win, nperseg_int = signal_helper._triage_segments(
      window, nperseg if nperseg is None else nperseg_int,
      input_length=x.shape[axis], dtype=x.dtype)

  if noverlap is None:
    noverlap_int = nperseg_int // 2
  else:
    noverlap_int = core.concrete_or_error(
        int, noverlap, "noverlap of windowed-FFT")

  if nfft is None:
    nfft_int = nperseg_int
  else:
    nfft_int = core.concrete_or_error(int, nfft, "nfft of windowed-FFT")

  # Special cases for size == 0
  if y is None:

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Ensure nperseg >= 1, e.g. nperseg = max(1, nperseg)
  2. Keep nperseg as a Python int static value, not a tracer; close over it in jit or pass via static_argnums
  3. Guard segment-count arithmetic against zero/negative results

Example fix

// before
nperseg = len(x) // n_segments  # can be 0
jax.scipy.signal.stft(x, nperseg=nperseg)
// after
nperseg = max(1, len(x) // n_segments)
jax.scipy.signal.stft(x, nperseg=nperseg)
Defensive patterns

Strategy: validation

Validate before calling

nperseg = int(nperseg) if nperseg is not None else 256
assert isinstance(nperseg, int) and nperseg >= 1

Type guard

def valid_nperseg(n) -> bool:
    return isinstance(n, (int,)) and not isinstance(n, bool) and n >= 1

Prevention

When it happens

Trigger: stft(x, nperseg=0) or nperseg=-256; nperseg computed from a traced value inside jax.jit; passing a float like 256.0 that converts to a bad value.

Common situations: Dividing signal length by a variable number of segments that can hit zero; config math like nperseg = len(x) // nseg with nseg > len(x).

Related errors


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