huggingface / huggingface/diffusers

InpaintProcessor.preprocess returns a bare tensor when no mask is passed, breaking its own 3-value contract

Open Beginner friendly
#14,470 1 comment 0 reactions 0 assignees View on GitHub
bug pipelines
Dominant language
Python
Stars
34.5k
Forks
7.3k
Avg merge
3d 3h
Merged PRs (30d)
91

Description

### Describe the bug

`InpaintProcessor.preprocess` returns `(image, mask, postprocessing_kwargs)` on every path except the `mask is None` early return ([`image_processor.py#L895-L897`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/image_processor.py#L895-L897)), which returns the processed image on its own. Unpacking the three values the rest of the method promises then raises:

```
ValueError: not enough values to unpack (expected 3, got 1)
```

The return annotation is `tuple[torch.Tensor, torch.Tensor]`, which no path actually returns, every masked path returns three values.

Both the early return and the three-value contract were introduced in the same commit (`f50b18eec`, #12220), so this looks like the early return simply not being updated when `postprocessing_kwargs` was added, rather than an intentional two-shape API.

Both in-repo call sites unpack three values (`modular_pipelines/qwenimage/encoders.py#L1144` and `#L1236`), but their `mask_image` input is `required=True`, so they never reach the branch. It is reachable through direct use of `InpaintProcessor`, which is exported from `diffusers` and documented in `docs/source/en/api/image_processor.md`.

### Reproduction

```python
import numpy as np
import PIL.Image

from diffusers.image_processor import InpaintProcessor

image = PIL.Image.fromarray(np.zeros((64, 64, 3), dtype=np.uint8))
mask = PIL.Image.fromarray(np.zeros((64, 64), dtype=np.uint8))

processor = InpaintProcessor()

print(len(processor.preprocess(image, mask=mask, height=64, width=64))) # 3
print(type(processor.preprocess(image, height=64, width=64))) #

img, msk, kwargs = processor.preprocess(image, height=64, width=64)
```

Output:

```
3

Traceback (most recent call last):
...
ValueError: not enough values to unpack (expected 3, got 1)
```

### Logs

```shell

```

### System Info

- 🤗 Diffusers version: 0.40.0.dev0 (`main`)
- Platform: macOS-26.6-arm64-arm-64bit-Mach-O
- Python version: 3.13.7
- PyTorch version (GPU?): 2.13.0 (False)
- Huggingface_hub version: 1.27.0
- Safetensors version: 0.8.0
- Accelerator: Apple M3
- Using GPU in script?: No
- Using distributed or parallel set-up in script?: No

### Who can help?

@DN6 @yiyixuxu

Contributor guide

Open the contributing guide

Research direction

Start in src/diffusers/image_processor.py around lines 895-897 and compare the no-mask path with the masked returns. Check the unpacking call sites in modular_pipelines/qwenimage/encoders.py and the API documentation in docs/source/en/api/image_processor.md. Done means InpaintProcessor.preprocess has one consistent three-value contract and the reproduction no longer raises when mask is omitted.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, pytorch
Domain
computer-vision, machine-learning
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.