keras-team/keras · error · ValueError

`patches` has unexpected rank for 3D reconstruction. Expecte

Error message

`patches` has unexpected rank for 3D reconstruction. Expected 4 (unbatched) or 5 (batched). Received shape: {patches.shape}

What it means

The 3D reconstruction path requires patches of rank 4 (unbatched: flat, gD, gH, gW) or rank 5 (batched: B, flat, gD, gH, gW) after layout handling. Any other rank cannot be a 3D patch grid, so it raises before reshaping.

Source

Thrown at keras/src/ops/image.py:1362

            patches = backend.numpy.transpose(patches, axes=(0, 2, 3, 4, 1))
        else:
            raise ValueError(
                "`patches` has unexpected rank for 3D channels_first "
                "reconstruction. Expected 4 (unbatched) or 5 (batched). "
                f"Received shape: {patches.shape}"
            )
        result = _reconstruct_patches_3d(
            patches, size, output_size, strides, padding, "channels_last"
        )
        if len(result.shape) == 4:
            return backend.numpy.transpose(result, axes=(3, 0, 1, 2))
        return backend.numpy.transpose(result, axes=(0, 4, 1, 2, 3))

    pD, pH, pW = size
    D, H, W = output_size

    if len(patches.shape) not in (4, 5):
        raise ValueError(
            "`patches` has unexpected rank for 3D reconstruction. "
            "Expected 4 (unbatched) or 5 (batched). "
            f"Received shape: {patches.shape}"
        )

    _unbatched = False
    if len(patches.shape) == 4:
        _unbatched = True
        patches = backend.numpy.expand_dims(patches, axis=0)

    shp = ops.shape(patches)
    B, gD, gH, gW = shp[0], shp[1], shp[2], shp[3]
    static_flat = patches.shape[-1]
    if static_flat is None:
        C = shp[4] // (pD * pH * pW)
    else:
        if static_flat % (pD * pH * pW) != 0:
            raise ValueError(

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Use the 2D reconstruct path for 2D patches (size length 2, rank-3/4 patches)
  2. Ensure patches rank is 5 batched or 4 unbatched for 3D; add/remove batch axis with expand_dims/squeeze as needed
  3. Print patches.shape right before the call and match it to (B, flat, gD, gH, gW)

Example fix

# before
reconstruct_patches(patches_2d, size=(8,8), output_size=(16,28,28))

# after
reconstruct_patches(patches_2d, size=(8,8), output_size=(28,28))
Defensive patterns

Strategy: validation

Validate before calling

assert len(patches.shape) in (4, 5), f'unexpected rank {len(patches.shape)}'
assert len(size) == 3 and len(output_size) == 3

Type guard

def is_3d_patches(patches) -> bool:
    return len(patches.shape) in (4, 5)

Prevention

When it happens

Trigger: reconstruct_patches_3d reached via a rank-3 or rank-6 patches tensor, or 2D image patches (rank 4 but wrong semantics) passed with a 3-element size triggering the 3D branch.

Common situations: Calling the 3D path with 2D patches or vice versa; extra leading dims from a dataset batch; squeezing the wrong axis during preprocessing.

Related errors


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/31e2c73866bdff32. Report an issue: GitHub.