{"record":{"id":"ab537af749794000","repo":"jax-ml/jax","slug":"mode-must-be-one-of-full-valid-same-got","errorCode":null,"errorMessage":"mode must be one of 'full', 'valid', 'same'; got {mode!r}.","messagePattern":"mode must be one of 'full', 'valid', 'same'; got (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/scipy/linalg.py","lineNumber":2861,"sourceCode":"    Array([[ 4, -1,  0,  0,  0],\n           [-2,  4, -1,  0,  0],\n           [ 0, -2,  4, -1,  0],\n           [ 0,  0, -2,  4, -1],\n           [ 0,  0,  0, -2,  4]], dtype=int32)\n  \"\"\"\n  n = operator.index(n)\n  if n <= 0:\n    raise ValueError(f\"n must be a positive integer; got {n}.\")\n  check_arraylike(\"convolution_matrix\", a)\n  a_arr = jnp.asarray(a)\n  if a_arr.ndim == 0:\n    raise ValueError(\n        \"convolution_matrix: a must be at least 1-dimensional, got a scalar.\")\n  m = a_arr.shape[-1]\n  if m < 1:\n    raise ValueError(f\"len(a) must be at least 1; got shape {a_arr.shape}.\")\n  if mode not in ('full', 'valid', 'same'):\n    raise ValueError(\n        f\"mode must be one of 'full', 'valid', 'same'; got {mode!r}.\")\n  pad_widths = [(0, 0)] * (a_arr.ndim - 1) + [(0, n - 1)]\n  az = jnp.pad(a_arr, pad_widths)\n  raz = jnp.pad(jnp.flip(a_arr, axis=-1), pad_widths)\n  L = m + n - 1\n  if mode == 'same':\n    trim = min(n, m) - 1\n    tb = trim // 2\n    te = trim - tb\n  elif mode == 'valid':\n    tb = min(n, m) - 1\n    te = tb\n  else:  # 'full'\n    tb = 0\n    te = 0\n  col0 = lax.slice_in_dim(az, tb, L - te, axis=-1)\n  row0 = lax.slice_in_dim(raz, L - n - tb, L - tb, axis=-1)\n  return toeplitz(col0, row0)","sourceCodeStart":2843,"sourceCodeEnd":2879,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/scipy/linalg.py#L2843-L2879","documentation":"convolution_matrix accepts only mode='full', 'valid', or 'same' (matching numpy.convolve/np.correlate semantics). Any other value — including 'circ', 'Same', None, or a typo — reaches the ValueError with repr of the bad mode. The comparison is case-sensitive.","triggerScenarios":"Calling convolution_matrix(a, n, mode='circ'); mode='FULL'; mode=None; mode supplied from config without validation.","commonSituations":"Confusion with scipy.signal.convolve/convolve2d which accept mode='full','valid','same' too but where users also know boundary= options; passing a mode meant for FFT convolution ('wrap'); porting code that stored mode in a settings dict.","solutions":["Use exactly one of 'full', 'valid', 'same' (lowercase)","Normalize user/config input with mode.lower() and whitelist-check before calling","For circular convolution use a different approach (pad+roll or FFT manually)"],"exampleFix":"# before\nC = convolution_matrix(a, n, mode='circ')\n# after\nC = convolution_matrix(a, n, mode='full')","handlingStrategy":"validation","validationCode":"MODES = ('full', 'valid', 'same')\nif mode not in MODES:\n    raise ValueError(f'mode must be one of {MODES}, got {mode!r}')\nC = convolution_matrix(a, n, mode=mode)","typeGuard":"def is_valid_conv_mode(m) -> bool:\n    return isinstance(m, str) and m in ('full', 'valid', 'same')","tryCatchPattern":"try:\n    convolution_matrix(a, n, mode=mode)\nexcept ValueError as e:\n    if 'mode must be one of' in str(e):\n        mode = 'full'; convolution_matrix(a, n, mode=mode)\n    else: raise","preventionTips":["Share a MODES whitelist constant between convolution utilities and config validation","Normalize case on mode strings from user input","Remember JAX follows numpy.convolve modes, not FFT-boundary options"],"tags":["jax","convolution-matrix","argument-validation","invalid-enum-argument"],"backgroundTag":"invalid-enum-argument","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}