{"record":{"id":"27168e348bf7533e","repo":"jax-ml/jax","slug":"in1-and-in2-must-have-the-same-number-of-dimension","errorCode":null,"errorMessage":"in1 and in2 must have the same number of dimensions","messagePattern":"in1 and in2 must have the same number of dimensions","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/scipy/signal.py","lineNumber":166,"sourceCode":"    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\n  no_swap = all(s1 >= s2 for s1, s2 in zip(in1.shape, in2.shape))\n  swap = all(s1 <= s2 for s1, s2 in zip(in1.shape, in2.shape))\n  if not (no_swap or swap):\n    raise ValueError(\"One input must be smaller than the other in every dimension.\")\n\n  shape_o = in2.shape\n  if swap:\n    in1, in2 = in2, in1\n  shape = in2.shape\n  in2 = jnp.flip(in2)\n\n  if mode == 'valid':\n    padding = [(0, 0) for s in shape]\n  elif mode == 'same':","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/scipy/signal.py#L148-L184","documentation":"_convolve_nd requires in1.ndim == in2.ndim; unlike some frameworks it does not auto-promote ranks for convolution. Note padding semantics differ from jnp.convolve, hence the separate implementation.","triggerScenarios":"convolve2d expects 2D inputs; passing a (H,W) image with a (K,) kernel, or a batched (N,H,W) with a 2D filter.","commonSituations":"1D-vs-2D kernel confusion, batched inputs forgetting the leading dim on the filter.","solutions":["Reshape to match ranks: kernel[None, :] for 2D, kernel[None, None] for batched 3D","Use jnp.squeeze on stray unit dims deliberately","Prefer fftconvolve with axes= for selective convolution"],"exampleFix":"# before\nsignal.convolve2d(img, kernel1d, mode='same')\n# after\nsignal.convolve2d(img, kernel1d[None, :], mode='same')","handlingStrategy":"validation","validationCode":"assert in1.ndim == in2.ndim, (in1.shape, in2.shape)","typeGuard":"def same_rank(a, b) -> bool: return jnp.asarray(a).ndim == jnp.asarray(b).ndim","tryCatchPattern":null,"preventionTips":["Use a helper that reshapes kernels to input rank automatically"],"tags":["jax","scipy","signal","convolution","shape-mismatch"],"backgroundTag":"argument-shape-mismatch","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}