{"record":{"id":"1141f6ba2180124b","repo":"keras-team/keras","slug":"padding-valid-requires-output-size-to-equal-si-1141f6","errorCode":null,"errorMessage":"`padding='valid'` requires output_size to equal size * grid. Got output_size=({D},{H},{W}), grid=({gD},{gH},{gW}), size=({pD},{pH},{pW}).","messagePattern":"`padding='valid'` requires output_size to equal size \\* grid\\. Got output_size=\\((.+?),(.+?),(.+?)\\), grid=\\((.+?),(.+?),(.+?)\\), size=\\((.+?),(.+?),(.+?)\\)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/ops/image.py","lineNumber":1436,"sourceCode":"                f\"be in the range ((gW-1)*pW, gW*pW], i.e. \"\n                f\"({static_gW * pW - pW}, {static_gW * pW}]. \"\n                f\"Got: gW={static_gW}, pW={pW}.\"\n            )\n        pad_total_d = gD * pD - D\n        pad_total_h = gH * pH - H\n        pad_total_w = gW * pW - W\n        begin = [\n            0,\n            pad_total_d // 2,\n            pad_total_h // 2,\n            pad_total_w // 2,\n            0,\n        ]\n        out_shape = [B, D, H, W, C]\n        x = ops.slice(x, begin, out_shape)\n    else:\n        if gD * pD != D or gH * pH != H or gW * pW != W:\n            raise ValueError(\n                f\"`padding='valid'` requires output_size to equal \"\n                f\"size * grid. Got output_size=({D},{H},{W}), \"\n                f\"grid=({gD},{gH},{gW}), size=({pD},{pH},{pW}).\"\n            )\n\n    if _unbatched:\n        x = backend.numpy.squeeze(x, axis=0)\n    return x\n\n\nclass MapCoordinates(Operation):\n    def __init__(self, order, fill_mode=\"constant\", fill_value=0, *, name=None):\n        super().__init__(name=name)\n        self.order = order\n        self.fill_mode = fill_mode\n        self.fill_value = fill_value\n\n    def call(self, inputs, coordinates):","sourceCodeStart":1418,"sourceCodeEnd":1454,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/ops/image.py#L1418-L1454","documentation":"With padding='valid', 3D reconstruct_tiles patches with no crop, so output_size must equal grid*patch on every axis: (D,H,W)==(gD*pD, gH*pH, gW*pW). Any mismatch raises.","triggerScenarios":"reconstruct_patches(..., padding='valid') (default) on 3D patches with any axis of output_size != grid*patch for that axis.","commonSituations":"Default padding forgotten while passing the original same-padded volume size; extracting with 'same' but reconstructing with 'valid'; per-axis dimension mix-ups in (D,H,W).","solutions":["Compute output_size from the patches grid: (gD*pD, gH*pH, gW*pW)","If extraction used 'same', pass padding='same' with the original volume size","Print patches.shape and size, then assert equality per axis"],"exampleFix":"# before\nreconstruct_patches(p, size=(4,8,8), output_size=(10,28,28))\n\n# after\ngD, gH, gW = p.shape[1], p.shape[2], p.shape[3]\nreconstruct_patches(p, size=(4,8,8), output_size=(gD*4, gH*8, gW*8))","handlingStrategy":"validation","validationCode":"gD, gH, gW = patches.shape[1], patches.shape[2], patches.shape[3]\nexpected = (gD*size[0], gH*size[1], gW*size[2])\nassert tuple(output_size) == expected, f'{output_size} != {expected}'","typeGuard":"def valid_3d_consistent(patches, size, output_size) -> bool:\n    g = patches.shape[1:4]\n    return tuple(output_size) == (g[0]*size[0], g[1]*size[1], g[2]*size[2])","tryCatchPattern":null,"preventionTips":["Compute output_size from the grid, never store a stale constant","Pair extract/reconstruct calls with identical padding/strides"],"tags":["keras","image","patches","shape-mismatch","input-validation"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}