jax-ml/jax · error · ValueError

nfft must be greater than or equal to nperseg.

Error message

nfft must be greater than or equal to nperseg.

What it means

nfft (FFT length) zero-pads each segment and must be at least nperseg so the windowed segment fits; a smaller nfft would truncate data. If nfft is not given it defaults to nperseg, so this only fires when an explicit too-small nfft is passed.

Source

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

  # Move time-axis to the end
  x = jnp.moveaxis(x, axis, -1)
  if y is not None and y_arr.ndim > 1:
    y_arr = jnp.moveaxis(y_arr, axis, -1)

  # Check if x and y are the same length, zero-pad if necessary
  if y is not None and x.shape[-1] != y_arr.shape[-1]:
    if x.shape[-1] < y_arr.shape[-1]:
      pad_shape = list(x.shape)
      pad_shape[-1] = y_arr.shape[-1] - x.shape[-1]
      x = jnp.concatenate((x, jnp.zeros_like(x, shape=pad_shape)), -1)
    else:
      pad_shape = list(y_arr.shape)
      pad_shape[-1] = x.shape[-1] - y_arr.shape[-1]
      y_arr = jnp.concatenate((y_arr, jnp.zeros_like(x, shape=pad_shape)), -1)

  if nfft_int < nperseg_int:
    raise ValueError('nfft must be greater than or equal to nperseg.')
  if noverlap_int >= nperseg_int:
    raise ValueError('noverlap must be less than nperseg.')
  nstep = nperseg_int - noverlap_int

  # Apply paddings
  if boundary is not None:
    ext_func = boundary_funcs[boundary]
    x = ext_func(x, nperseg_int // 2, axis=-1)
    if y is not None:
      y_arr = ext_func(y_arr, nperseg_int // 2, axis=-1)

  if padded:
    # Pad to integer number of windowed segments
    # I.e make x.shape[-1] = nperseg + (nseg-1)*nstep, with integer nseg
    nadd = (-(x.shape[-1]-nperseg_int) % nstep) % nperseg_int
    x = jnp.concatenate((x, jnp.zeros_like(x, shape=(*x.shape[:-1], nadd))), axis=-1)
    if y is not None:
      y_arr = jnp.concatenate((y_arr, jnp.zeros_like(x, shape=(*y_arr.shape[:-1], nadd))), axis=-1)

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Set nfft >= nperseg (commonly the next power of two above nperseg)
  2. Omit nfft to default it to nperseg
  3. Compute nfft = max(nfft, nperseg) defensively in config-driven code

Example fix

// before
jax.scipy.signal.stft(x, nperseg=500, nfft=256)
// after
jax.scipy.signal.stft(x, nperseg=500, nfft=512)
Defensive patterns

Strategy: validation

Validate before calling

if nfft is not None:
    nfft = max(int(nfft), int(nperseg))

Prevention

When it happens

Trigger: stft(x, nperseg=256, nfft=128); copying nfft from a config where nperseg was smaller; nfft set to a power of two below the segment size for 'efficiency'.

Common situations: Tuning FFT sizes for frequency resolution and choosing nfft < window length by mistake.

Related errors


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