{"record":{"id":"947bff4bab39161c","repo":"jax-ml/jax","slug":"convolve2d-only-supports-boundary-fill-fillva","errorCode":null,"errorMessage":"convolve2d() only supports boundary='fill', fillvalue=0","messagePattern":"convolve2d\\(\\) only supports boundary='fill', fillvalue=0","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"jax/_src/scipy/signal.py","lineNumber":325,"sourceCode":"           [13., 30., 32., 20.],\n           [ 3., 13., 18.,  8.]], dtype=float32)\n\n    Specifying ``mode = 'same'`` returns a centered 2D convolution of the same size\n    as the first input:\n\n    >>> jax.scipy.signal.convolve2d(x, y, mode='same')\n    Array([[22., 17.],\n           [30., 32.]], dtype=float32)\n\n    Specifying ``mode = 'valid'`` returns only the portion of 2D convolution\n    where the two arrays fully overlap:\n\n    >>> jax.scipy.signal.convolve2d(x, y, mode='valid')\n    Array([[22., 17.],\n           [30., 32.]], dtype=float32)\n  \"\"\"\n  if boundary != 'fill' or fillvalue != 0:\n    raise NotImplementedError(\"convolve2d() only supports boundary='fill', fillvalue=0\")\n  if np.ndim(in1) != 2 or np.ndim(in2) != 2:\n    raise ValueError(\"convolve2d() only supports 2-dimensional inputs.\")\n  return _convolve_nd(in1, in2, mode, precision=precision)\n\n\ndef correlate(in1: Array, in2: Array, mode: ModeString = 'full', method: str = 'auto',\n              precision: PrecisionLike = None) -> Array:\n  \"\"\"Cross-correlation of two N-dimensional arrays.\n\n  JAX implementation of :func:`scipy.signal.correlate`.\n\n  Args:\n    in1: left-hand input to the cross-correlation.\n    in2: right-hand input to the cross-correlation. Must have ``in1.ndim == in2.ndim``.\n    mode: controls the size of the output. Available operations are:\n\n      * ``\"full\"``: (default) output the full cross-correlation of the inputs.\n      * ``\"same\"``: return a centered portion of the ``\"full\"`` output which","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/scipy/signal.py#L307-L343","documentation":"convolve2d in JAX only implements zero-padding (boundary='fill', fillvalue=0); unlike SciPy it does not support 'wrap', 'reflect', or nonzero fill values, because the underlying lax convolution only exposes explicit padding. Passing anything else raises NotImplementedError.","triggerScenarios":"jax.scipy.signal.convolve2d(x, k, boundary='wrap'); boundary='symm'; or fillvalue=1.0 — common in image-processing code ported from scipy.signal.","commonSituations":"Migrating scipy.signal.convolve2d image filters (e.g. Laplacian with symmetric boundaries) to JAX.","solutions":["Use boundary='fill', fillvalue=0 and manually pad the input with jnp.pad(mode='wrap'/'symmetric') to the equivalent extent, then use mode='valid'","Use jax.lax.conv_general_dilated with a custom padding config for asymmetric padding","Keep that operation in scipy/numpy on CPU if boundary semantics are essential"],"exampleFix":"// before\ny = jax.scipy.signal.convolve2d(x, k, boundary='wrap', mode='same')\n// after\nxp = jnp.pad(x, ((k.shape[0]//2,)*2, (k.shape[1]//2,)*2), mode='wrap')\ny = jax.scipy.signal.convolve2d(xp, k, mode='valid')","handlingStrategy":"fallback","validationCode":"def conv2d_wrap(x, k, mode='same'):\n    # emulate wrap boundary via explicit padding\n    ph, pw = k.shape[0] // 2, k.shape[1] // 2\n    xp = jnp.pad(x, ((ph, ph), (pw, pw)), mode='wrap')\n    return jax.scipy.signal.convolve2d(xp, k, mode='valid')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never forward scipy boundary kwargs to JAX signal functions","Emulate non-fill boundaries with jnp.pad + mode='valid'"],"tags":["jax","scipy","convolution","not-implemented","boundary"],"backgroundTag":"unsupported-feature-argument","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}