jax-ml/jax · error · ValueError
Breakpoints must be non-negative and less than length of dat
Error message
Breakpoints must be non-negative and less than length of data along given axis.
What it means
For linear detrending, breakpoints are combined with 0 and N (data length along axis) and must lie within [0, N]. A negative breakpoint or one exceeding the axis length raises this error, because piecewise fitting would reference nonexistent data.
Source
Thrown at jax/_src/scipy/signal.py:539
>>> with jnp.printoptions(precision=3): # suppress float error
... print("Detrended:", detrended)
... print("Underlying trend:", data - detrended)
Detrended: [-5. -2. 2. 2. 3.]
Underlying trend: [6. 6. 6. 6. 6.]
"""
if overwrite_data is not None:
raise NotImplementedError("overwrite_data argument not implemented.")
if type not in ['constant', 'linear']:
raise ValueError("Trend type must be 'linear' or 'constant'.")
data_arr, = promote_dtypes_inexact(jnp.asarray(data))
if type == 'constant':
return data_arr - data_arr.mean(axis, keepdims=True)
else:
N = data_arr.shape[axis]
# bp is static, so we use np operations to avoid pushing to device.
bp_arr = np.sort(np.unique(np.r_[0, bp, N]))
if bp_arr[0] < 0 or bp_arr[-1] > N:
raise ValueError("Breakpoints must be non-negative and less than length of data along given axis.")
data_arr = jnp.moveaxis(data_arr, axis, 0)
shape = data_arr.shape
data_arr = data_arr.reshape(N, -1)
for m in range(len(bp_arr) - 1):
Npts = bp_arr[m + 1] - bp_arr[m]
A = jnp.vstack([
jnp.ones(Npts, dtype=data_arr.dtype),
jnp.arange(1, Npts + 1, dtype=data_arr.dtype) / Npts.astype(data_arr.dtype)
]).T
sl = slice(bp_arr[m], bp_arr[m + 1])
coef, *_ = linalg.lstsq(A, data_arr[sl])
data_arr = data_arr.at[sl].add(-jnp.matmul(A, coef, precision=lax.Precision.HIGHEST))
return jnp.moveaxis(data_arr.reshape(shape), 0, axis)
def _fft_helper(x: Array, win: Array, detrend_func: Callable[[Array], Array],
nperseg: int, noverlap: int, nfft: int | None, sides: str) -> Array:
"""Calculate windowed FFT in the same way the original SciPy does.View on GitHub (pinned to 1e1c6a8fc0)
Solutions
- Clamp/validate breakpoints to 0 <= bp <= x.shape[axis] before calling
- Recompute breakpoints from the current data length (indices, not physical units)
- Verify the axis argument matches the axis the breakpoints were computed on
Example fix
// before jax.scipy.signal.detrend(x, type='linear', bp=bps) // after N = x.shape[axis] bps = [b for b in bps if 0 <= b <= N] jax.scipy.signal.detrend(x, type='linear', bp=bps)
Defensive patterns
Strategy: validation
Validate before calling
N = x.shape[axis] bp = [b for b in bp if 0 <= b <= N] assert len(bp) > 0 or not bp, 'breakpoints filtered'
Prevention
- Derive breakpoints from x.shape[axis], not hardcoded indices
- Recheck breakpoints after slicing or resampling the data
When it happens
Trigger: detrend(x, type='linear', bp=[-2]) or bp=[50] on an axis of length 40; reusing breakpoints computed against a different (longer) dataset or after reshaping.
Common situations: Hardcoded breakpoint indices from earlier data; off-by-one after slicing; breakpoints derived from timestamps not sample indices.
Related errors
- overwrite_data argument not implemented.
- Trend type must be 'linear' or 'constant'.
- dot_general requires lhs dimension numbers to be nonnegative
- dot_general requires rhs dimension numbers to be nonnegative
- ragged_dot_general requires {dim_name} numbers to be nonnega
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/bbb5ed3d05fecff8.
Report an issue: GitHub.