matplotlib/matplotlib · error · ValueError

noverlap must be less than NFFT

Error message

noverlap must be less than NFFT

What it means

mlab._spectral_helper, the engine behind psd/csd/coherence/spectrogram, segments the signal into NFFT-length windows stepped by (NFFT - noverlap); it enforces 0 <= noverlap < NFFT because overlap equal to or larger than the window makes the step zero or negative, so no segments could be produced. NFFT=None defaults to 256 before the check runs.

Source

Thrown at lib/matplotlib/mlab.py:253

        # implement the core of psd(), csd(), and spectrogram() without doing
        # extra calculations.  We return the unaveraged Pxy, freqs, and t.
        same_data = y is x

    if Fs is None:
        Fs = 2
    if noverlap is None:
        noverlap = 0
    if detrend_func is None:
        detrend_func = detrend_none
    if window is None:
        window = window_hanning

    # if NFFT is set to None use the whole signal
    if NFFT is None:
        NFFT = 256

    if not (0 <= noverlap < NFFT):
        raise ValueError('noverlap must be less than NFFT')

    if mode is None or mode == 'default':
        mode = 'psd'
    _api.check_in_list(
        ['default', 'psd', 'complex', 'magnitude', 'angle', 'phase'],
        mode=mode)

    if not same_data and mode != 'psd':
        raise ValueError("x and y must be equal if mode is not 'psd'")

    # Make sure we're dealing with a numpy array. If y and x were the same
    # object to start with, keep them that way
    x = np.asarray(x)
    if not same_data:
        y = np.asarray(y)

    if sides is None or sides == 'default':
        if np.iscomplexobj(x):

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Keep noverlap strictly below NFFT; the idiomatic choice is noverlap = NFFT // 2 (50% overlap).
  2. If you need more overlap, raise NFFT accordingly (e.g. NFFT=noverlap + 64).
  3. Validate/clip before calling: noverlap = max(0, min(noverlap, NFFT - 1)).
  4. Remember NFFT=None silently becomes 256 — pass an explicit NFFT when tuning noverlap.

Example fix

# before
Pxx, freqs = mlab.psd(x, NFFT=128, Fs=fs, noverlap=128)

# after
Pxx, freqs = mlab.psd(x, NFFT=128, Fs=fs, noverlap=64)  # 50% overlap
Defensive patterns

Strategy: validation

Validate before calling

def clamp_spectral_params(NFFT, noverlap):
    NFFT = 256 if NFFT is None else NFFT
    noverlap = 0 if noverlap is None else noverlap
    assert 0 <= noverlap < NFFT, f'need 0 <= noverlap < NFFT, got {noverlap=}, {NFFT=}'
    return NFFT, min(noverlap, NFFT - 1)

Try / catch

try:
    Pxx, f = mlab.psd(x, NFFT=NFFT, noverlap=noverlap)
except ValueError as e:
    if 'noverlap' in str(e):
        Pxx, f = mlab.psd(x, NFFT=NFFT, noverlap=NFFT // 2)
    else:
        raise

Prevention

When it happens

Trigger: psd(x, NFFT=128, noverlap=128) or noverlap > NFFT; spectrogram(x, NFFT=256, noverlap=300); passing a negative noverlap; setting a large noverlap while leaving NFFT at its 256 default.

Common situations: Porting scipy.signal.spectrogram parameters (nperseg/noverlap) where relationships differ; copying examples that assume 50% overlap but forgetting to raise NFFT for finer resolution; computing noverlap dynamically (e.g. noverlap = int(0.75 * len(x))) without clamping to NFFT.

Related errors


AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21). Data as JSON: /api/errors/44fc418ff3089f41. Report an issue: GitHub.