{"record":{"id":"58f751992d4e176f","repo":"jax-ml/jax","slug":"unrecognized-mode","errorCode":null,"errorMessage":"Unrecognized {mode=}","messagePattern":"Unrecognized (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/scipy/signal.py","lineNumber":152,"sourceCode":"  if (all(s1 == 1 or s2 == 1 for s1, s2 in zip(in1.shape, in2.shape))):\n    conv = in1 * in2\n  else:\n    if jnp.iscomplexobj(in1):\n      fft, ifft = jnp.fft.fftn, jnp.fft.ifftn\n    else:\n      fft, ifft = jnp.fft.rfftn, jnp.fft.irfftn\n    sp1 = fft(in1, fft_shape)\n    sp2 = fft(in2, fft_shape)\n    conv = ifft(sp1 * sp2, fft_shape)\n\n  if mode == \"full\":\n    out_shape = full_shape\n  elif mode == \"same\":\n    out_shape = in1.shape\n  elif mode == \"valid\":\n    out_shape = tuple(s1 - s2 + 1 for s1, s2 in zip(in1.shape, in2.shape))\n  else:\n    raise ValueError(f\"Unrecognized {mode=}\")\n\n  start_indices = tuple((full_size - out_size) // 2\n                        for full_size, out_size in zip(full_shape, out_shape))\n  return lax.dynamic_slice(conv, start_indices, out_shape)\n\n\n# Note: we do not reuse the code from jax.numpy.convolve here, because the handling\n# of padding differs slightly between the two implementations (particularly for\n# mode='same').\ndef _convolve_nd(in1: Array, in2: Array, mode: ModeString, *, precision: PrecisionLike) -> Array:\n  if mode not in [\"full\", \"same\", \"valid\"]:\n    raise ValueError(\"mode must be one of ['full', 'same', 'valid']\")\n  if in1.ndim != in2.ndim:\n    raise ValueError(\"in1 and in2 must have the same number of dimensions\")\n  if in1.size == 0 or in2.size == 0:\n    raise ValueError(f\"zero-size arrays not supported in convolutions, got shapes {in1.shape} and {in2.shape}.\")\n  in1, in2 = promote_dtypes_inexact(in1, in2)\n","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/scipy/signal.py#L134-L170","documentation":"Defensive fallthrough in _fftconvolve_unbatched when mode is not 'full'/'same'/'valid' after slicing logic. Normally unreachable because fftconvolve validates mode earlier; it can fire via direct internal calls or monkeypatching.","triggerScenarios":"Calling the private _fftconvolve_unbatched with an unchecked mode; bypassing the public API validation.","commonSituations":"Internal code reuse where mode is passed through from another function without revalidation.","solutions":["Call the public fftconvolve/convolve instead of private helpers","Validate mode against ['full','same','valid'] before any internal pass-through"],"exampleFix":"# before\nout = _fftconvolve_unbatched(in1, in2, mode='circul')\n# after\nout = jax.scipy.signal.fftconvolve(in1, in2, mode='same')","handlingStrategy":"validation","validationCode":"assert mode in ('full','same','valid'), mode","typeGuard":"def is_mode(m: str) -> bool: return m in ('full', 'same', 'valid')","tryCatchPattern":null,"preventionTips":["Never call private _fftconvolve_unbatched directly"],"tags":["jax","scipy","signal","internal-api","argument-validation"],"backgroundTag":"invalid-enum-argument","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}