{"record":{"id":"9929d5f79213a02a","repo":"jax-ml/jax","slug":"nfft-must-be-greater-than-or-equal-to-nperseg","errorCode":null,"errorMessage":"nfft must be greater than or equal to nperseg.","messagePattern":"nfft must be greater than or equal to nperseg\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/scipy/signal.py","lineNumber":730,"sourceCode":"\n  # Move time-axis to the end\n  x = jnp.moveaxis(x, axis, -1)\n  if y is not None and y_arr.ndim > 1:\n    y_arr = jnp.moveaxis(y_arr, axis, -1)\n\n  # Check if x and y are the same length, zero-pad if necessary\n  if y is not None and x.shape[-1] != y_arr.shape[-1]:\n    if x.shape[-1] < y_arr.shape[-1]:\n      pad_shape = list(x.shape)\n      pad_shape[-1] = y_arr.shape[-1] - x.shape[-1]\n      x = jnp.concatenate((x, jnp.zeros_like(x, shape=pad_shape)), -1)\n    else:\n      pad_shape = list(y_arr.shape)\n      pad_shape[-1] = x.shape[-1] - y_arr.shape[-1]\n      y_arr = jnp.concatenate((y_arr, jnp.zeros_like(x, shape=pad_shape)), -1)\n\n  if nfft_int < nperseg_int:\n    raise ValueError('nfft must be greater than or equal to nperseg.')\n  if noverlap_int >= nperseg_int:\n    raise ValueError('noverlap must be less than nperseg.')\n  nstep = nperseg_int - noverlap_int\n\n  # Apply paddings\n  if boundary is not None:\n    ext_func = boundary_funcs[boundary]\n    x = ext_func(x, nperseg_int // 2, axis=-1)\n    if y is not None:\n      y_arr = ext_func(y_arr, nperseg_int // 2, axis=-1)\n\n  if padded:\n    # Pad to integer number of windowed segments\n    # I.e make x.shape[-1] = nperseg + (nseg-1)*nstep, with integer nseg\n    nadd = (-(x.shape[-1]-nperseg_int) % nstep) % nperseg_int\n    x = jnp.concatenate((x, jnp.zeros_like(x, shape=(*x.shape[:-1], nadd))), axis=-1)\n    if y is not None:\n      y_arr = jnp.concatenate((y_arr, jnp.zeros_like(x, shape=(*y_arr.shape[:-1], nadd))), axis=-1)","sourceCodeStart":712,"sourceCodeEnd":748,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/scipy/signal.py#L712-L748","documentation":"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.","triggerScenarios":"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'.","commonSituations":"Tuning FFT sizes for frequency resolution and choosing nfft < window length by mistake.","solutions":["Set nfft >= nperseg (commonly the next power of two above nperseg)","Omit nfft to default it to nperseg","Compute nfft = max(nfft, nperseg) defensively in config-driven code"],"exampleFix":"// before\njax.scipy.signal.stft(x, nperseg=500, nfft=256)\n// after\njax.scipy.signal.stft(x, nperseg=500, nfft=512)","handlingStrategy":"validation","validationCode":"if nfft is not None:\n    nfft = max(int(nfft), int(nperseg))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default nfft to nperseg and only increase it (zero-padding)","Use next power of two: nfft = 1 << (nperseg - 1).bit_length() when padding is wanted"],"tags":["jax","scipy","stft","fft-size","argument-validation"],"backgroundTag":"fft-size-smaller-than-window","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}