jax-ml/jax · error · ValueError

interior padding in padding_config must be nonnegative, got

Error message

interior padding in padding_config must be nonnegative, got padding_config {padding_config}

What it means

Each padding_config triple is (low, high, interior); interior padding inserts gaps of `interior` elements between existing elements, so it must be >= 0. JAX raises this ValueError when any interior value is negative — negative trimming is not supported by lax.pad.

Source

Thrown at jax/_src/lax/lax.py:7633

mlir.register_lowering(split_p, _split_lower)

def _pad_dtype_rule(operand, padding_value, *, padding_config):
  if operand.dtype != padding_value.dtype:
    msg = "pad operand and padding_value must be same dtype: got {} and {}."
    raise TypeError(msg.format(operand.dtype, padding_value.dtype))

  return input_dtype(operand, padding_value)

def _pad_shape_rule(operand, padding_value, *, padding_config):
  if np.ndim(padding_value) != 0:
    raise ValueError(f"padding_value must be a scalar; got {np.shape(padding_value)=}")
  op_shape = np.shape(operand)
  if not len(padding_config) == np.ndim(operand):
    raise ValueError("length of padding_config must equal the number of axes "
                     f"of operand, got padding_config {padding_config} "
                     f"for operand shape {op_shape}")
  if not all(i >= 0 for _, _, i in padding_config):
    raise ValueError("interior padding in padding_config must be nonnegative, "
                     f"got padding_config {padding_config}")
  result = tuple(l + h + core.dilate_dim(d, i + 1)
                 for (l, h, i), d in zip(padding_config, op_shape))
  if not all(d >= 0 for d in result):
    msg = (f"Dimension size after padding is not at least 0, "
           f"got result shape {result}, for padding_config {padding_config}"
           f" and operand shape {op_shape}")
    raise ValueError(msg)
  return result

def _pad_sharding_rule(operand, padding_value, *, padding_config):
  # TODO(yashkatariya): Once JAX supports uneven sharding at the top level,
  # change this logic to `return operand.sharding` directly.
  out_shape = _pad_shape_rule(operand, padding_value,
                              padding_config=padding_config)
  return slicing._get_sharding_for_varying_out_shape(
      out_shape, operand, 'padding')

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Use slicing to crop instead: x[1:-1, ...] for negative low/high; lax.pad cannot trim
  2. Clamp interior values: max(0, interior) if you only want to skip gaps
  3. Double-check tuple order: (low, high, interior) — negatives are invalid everywhere at trace time for interior

Example fix

# before
y = jax.lax.pad(x, 0, [(0, 0, -1), (0, 0, -1)])  # trying to drop gaps
# after
y = x[:, ::2]  # or slice to crop; lax.pad cannot trim
Defensive patterns

Strategy: validation

Validate before calling

assert all(i >= 0 for _, _, i in padding_config), padding_config
padding_config = [(l, h, max(0, i)) for l, h, i in padding_config]

Type guard

def valid_interior(config) -> bool:
    return all(i >= 0 for _, _, i in config)

Prevention

When it happens

Trigger: Passing (-1, -1, 0) intending to crop the array; using negative 'padding' from another framework's slicing semantics; sign errors in computed pad widths.

Common situations: Porting PyTorch/TF code that allows negative padding to crop; attempts to implement 'same' padding by subtracting and going negative on the interior field; typos in config tuples.

Related errors


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