jax-ml/jax · error · ValueError

Negative padding is larger than the size of the correspondin

Error message

Negative padding is larger than the size of the corresponding dimension: got padding={pads} for lhs_shape[2:]={lhs_shape[2:]}

What it means

Explicit negative padding can shrink the effective input below zero; when the padded lhs spatial dims would become negative, conv_shape_tuple raises this ValueError instead of producing a nonsensical shape. Negative padding itself is legal (cropping) but must not exceed the dimension size.

Source

Thrown at jax/_src/lax/convolution.py:909

  shape = list(x.shape)
  size2, ragged = divmod(shape[src], size1)
  assert not ragged
  shape[src:src+1] = [size1, size2]
  return lax.reshape(x, shape)


def conv_shape_tuple(lhs_shape, rhs_shape, strides, pads, batch_group_count=1):
  """Compute the shape tuple of a conv given input shapes in canonical order."""
  if isinstance(pads, str):
    pads = lax.padtype_to_pads(lhs_shape[2:], rhs_shape[2:], strides, pads)
  if len(pads) != len(lhs_shape) - 2:
    msg = "Wrong number of explicit pads for convolution: expected {}, got {}."
    raise TypeError(msg.format(len(lhs_shape) - 2, len(pads)))

  lhs_padded = np.add(lhs_shape[2:], np.sum(np.array(pads).reshape(-1, 2),
                                              axis=1))
  if np.any(lhs_padded < 0):
    raise ValueError("Negative padding is larger than the size of the corresponding dimension: "
                     f"got padding={pads} for lhs_shape[2:]={lhs_shape[2:]}")
  out_space = tuple(map(core.stride_dim, lhs_padded, rhs_shape[2:], strides))
  if batch_group_count > 1:
    assert lhs_shape[0] % batch_group_count == 0
    out_shape_0 = lhs_shape[0] // batch_group_count
  else:
    out_shape_0 = lhs_shape[0]
  out_shape = (out_shape_0, rhs_shape[0])
  return tuple(out_shape + tuple(out_space))


def conv_general_shape_tuple(lhs_shape, rhs_shape, window_strides, padding,
                             dimension_numbers):
  lhs_perm, rhs_perm, out_perm = conv_general_permutations(dimension_numbers)
  lhs_trans = np.take(lhs_shape, lhs_perm)
  rhs_trans = np.take(rhs_shape, rhs_perm)
  out_trans = conv_shape_tuple(lhs_trans, rhs_trans, window_strides, padding)
  return tuple(np.take(out_trans, np.argsort(out_perm)))

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Reduce the negative padding so each spatial dim plus (lo+hi) stays >= 0
  2. Use string padding ('SAME'/'VALID') or non-negative pads instead of manual cropping
  3. Add a shape check in your model code to stop stacking before maps get too small

Example fix

# before
out = lax.conv_general_dilated(x, w, (2,2), ((-4,-4),(-4,-4)))  # x is 8x8
# after
out = lax.conv_general_dilated(x, w, (2,2), ((-2,-2),(-2,-2)))  # 8-4 >= 0
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
padded = np.add(np.array(lhs.shape)[2:], np.sum(np.array(pads), axis=1))
assert (padded >= 0).all(), f'negative effective dims: {padded}'

Prevention

When it happens

Trigger: Passing pads like ((-10,-10),(-10,-10)) to conv_general_dilated when the input spatial dims are smaller than 20, e.g. cropping more than the feature-map size.

Common situations: Using negative padding to emulate 'valid-ish' output sizes (e.g. kaiming-style cropping with stride>1) computed from formulae that overshoot small inputs; deep stacks where feature maps shrink below the crop amount.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/3990a788df079ad7. Report an issue: GitHub.