keras-team/keras · error · ValueError
`padding='valid'` requires output_size to equal size * grid.
Error message
`padding='valid'` requires output_size to equal size * grid. Got output_size=({H},{W}), grid=({gH},{gW}), size=({pH},{pW}). What it means
With padding='valid' (the default), reconstruct_patches (2D) tiles patches back with no padding to crop, so the result is exactly grid*patch per axis. The op raises when output_size != (gH*pH, gW*pW), since that size cannot be produced from this patch grid.
Source
Thrown at keras/src/ops/image.py:1308
f"Got: gH={static_gH}, pH={pH}."
)
if isinstance(static_gW, int) and not (
static_gW * pW - pW < W <= static_gW * pW
):
raise ValueError(
f"For `padding='same'`, `output_size` width ({W}) must "
f"be in the range ((gW-1)*pW, gW*pW], i.e. "
f"({static_gW * pW - pW}, {static_gW * pW}]. "
f"Got: gW={static_gW}, pW={pW}."
)
pad_total_h = gH * pH - H
pad_total_w = gW * pW - W
begin = [0, pad_total_h // 2, pad_total_w // 2, 0]
out_shape = [B, H, W, C]
x = ops.slice(x, begin, out_shape)
else:
if gH * pH != H or gW * pW != W:
raise ValueError(
f"`padding='valid'` requires output_size to equal "
f"size * grid. Got output_size=({H},{W}), "
f"grid=({gH},{gW}), size=({pH},{pW})."
)
if _unbatched:
x = backend.numpy.squeeze(x, axis=0)
return x
def _reconstruct_patches_3d(
patches,
size,
output_size,
strides=None,
padding="valid",
data_format=None,
):View on GitHub (pinned to 7a34a03db6)
Solutions
- Derive output_size from the patches tensor: (gH*pH, gW*pW) with gH,gW = patches.shape[1], patches.shape[2]
- If patches were extracted with padding='same', pass padding='same' and the original image size
- Verify strides: with strides<size the grid*patch exceeds the image and 'same' is required to crop
Example fix
# before reconstruct_patches(patches, size=(8,8), output_size=(28,28)) # after gH, gW = patches.shape[1], patches.shape[2] reconstruct_patches(patches, size=(8,8), output_size=(gH*8, gW*8))
Defensive patterns
Strategy: validation
Validate before calling
gH, gW = patches.shape[1], patches.shape[2] output_size = (gH*size[0], gW*size[1]) # valid: derive, don't guess
Type guard
def valid_size_consistent(patches, size, output_size) -> bool:
return (patches.shape[1]*size[0], patches.shape[2]*size[1]) == tuple(output_size) Prevention
- Remember padding defaults to 'valid'
- Derive output_size from patches.shape, never hardcode
When it happens
Trigger: reconstruct_patches(patches, size, output_size) (padding defaults to 'valid') with output_size not equal to (gH*pH, gW*pW), e.g. (B,4,4,64) patches, size=(8,8), output_size=(28,28) instead of (32,32).
Common situations: Forgetting the default is 'valid' and passing the original same-padded image size; extracting with padding='same' but reconstructing with 'valid'; using non-overlapping strides and assuming output equals original image size.
Related errors
- For `padding='same'`, `output_size` width ({W}) must be in t
- For `padding='same'`, `output_size` depth ({D}) must be in t
- `padding='valid'` requires output_size to equal size * grid.
- Invalid `output_size`. Expected length 3 (D, H, W). Got: out
- `patches` has unexpected rank for 3D reconstruction. Expecte
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/82681c8a3ce7b8c5.
Report an issue: GitHub.