PaddlePaddle/PaddleOCR · error · ValueError
Make sure that the channel dimension of the pixel values mat
Error message
Make sure that the channel dimension of the pixel values match with the one set in the configuration.
What it means
DonutSwinPatchEmbeddings.forward unpacks the input as (N, C, H, W) and requires C == self.num_channels (3 for the pretrained Swin tokenizer used by Donut/DOC-VQA rec models). Unlike the top-level model, this embeddings module does not repeat-interleave grayscale input, so a mismatch raises ValueError immediately.
Source
Thrown at ppocr/modeling/backbones/rec_donut_swin.py:368
)
def maybe_pad(self, pixel_values, height, width):
if width % self.patch_size[1] != 0:
pad_values = (0, self.patch_size[1] - width % self.patch_size[1])
if self.is_export:
pad_values = paddle.to_tensor(pad_values, dtype="int32")
pixel_values = nn.functional.pad(pixel_values, pad_values)
if height % self.patch_size[0] != 0:
pad_values = (0, 0, 0, self.patch_size[0] - height % self.patch_size[0])
if self.is_export:
pad_values = paddle.to_tensor(pad_values, dtype="int32")
pixel_values = nn.functional.pad(pixel_values, pad_values)
return pixel_values
def forward(self, pixel_values) -> Tuple[paddle.Tensor, Tuple[int]]:
_, num_channels, height, width = pixel_values.shape
if num_channels != self.num_channels:
raise ValueError(
"Make sure that the channel dimension of the pixel values match with the one set in the configuration."
)
pixel_values = self.maybe_pad(pixel_values, height, width)
embeddings = self.projection(pixel_values)
_, _, height, width = embeddings.shape
output_dimensions = (height, width)
embeddings = embeddings.flatten(2).transpose([0, 2, 1])
return embeddings, output_dimensions
# Copied from transformers.models.swin.modeling_swin.SwinPatchMerging
class DonutSwinPatchMerging(nn.Layer):
"""
Patch Merging Layer.
Args:View on GitHub (pinned to 2661c7c0ef)
Solutions
- Convert images to 3-channel RGB before batching: img = img.convert('RGB') in the preprocessing
- If you call DonutSwinModel.forward (not the embeddings directly), pass a non-None pixel_values tensor — it repeats 1-channel input to 3 automatically
- Align the config's num_channels with the actual input channels (default and pretrained weights expect 3)
Example fix
# before
img = Image.open(path) # may be L or RGBA
x = to_tensor(img).unsqueeze(0) # C=1 -> ValueError
# after
img = Image.open(path).convert('RGB')
x = to_tensor(img).unsqueeze(0) # C=3 Defensive patterns
Strategy: type-guard
Validate before calling
assert pixel_values.ndim == 4 and pixel_values.shape[1] == 3, \
f'expected (N, 3, H, W) input, got {tuple(pixel_values.shape)}' Type guard
def is_rgb_batch(t) -> bool:
return t.ndim == 4 and t.shape[1] == 3 Prevention
- Always convert('RGB') in the image preprocessing for Donut/DOC-VQA models
- Call DonutSwinModel.forward (auto-repeats 1-channel) instead of embeddings directly when feeding grayscale
- Assert channel dim right after batch collation, before the forward pass
When it happens
Trigger: Calling DonutSwinEmbeddings/patch embedding forward with a 1-channel tensor, or with 4-channel input (e.g. alpha kept, or RGBA PIL image converted with .tensor() without convert('RGB')); or building the backbone with a non-default num_channels and feeding normal images.
Common situations: Preprocessing pipeline that skips img.convert('RGB') for grayscale source scans (very common with document OCR), or a config where num_channels was changed to 1 without routing through DonutSwinModel.forward (which does repeat channel 1 to 3).
Related errors
- You have to specify pixel_values
- The input data is inconsistent with expectations.
- The input data is inconsistent with expectations.
- The input data is inconsistent with expectations.
- The input data is inconsistent with expectations.
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/84812b8f04aa7aeb.
Report an issue: GitHub.