immich-app/immich · error · HTTPException
Image has zero width or height
Error message
Image has zero width or height
What it means
Raised as HTTPException(400) by the /predict endpoint when the uploaded image decodes successfully (PIL) but has width==0 or height==0. The decode succeeds but the resulting image is degenerate and cannot be used for inference.
Source
Thrown at machine-learning/immich_ml/main.py:175
async def root() -> ORJSONResponse:
return ORJSONResponse({"message": "Immich ML"})
@app.get("/ping")
def ping() -> PlainTextResponse:
return PlainTextResponse("pong")
@app.post("/predict", dependencies=[Depends(update_state)])
async def predict(
entries: InferenceEntries = Depends(get_entries),
image: bytes | None = File(default=None),
text: str | None = Form(default=None),
) -> Any:
if image is not None:
decoded = await run(lambda: decode_pil(image))
if decoded.width == 0 or decoded.height == 0:
raise HTTPException(400, "Image has zero width or height")
inputs: Image | str = decoded
elif text is not None:
inputs = text
else:
raise HTTPException(400, "Either image or text must be provided")
response = await run_inference(inputs, entries)
return ORJSONResponse(response)
async def run_inference(payload: Image | str, entries: InferenceEntries) -> InferenceResponse:
outputs: dict[ModelIdentity, Any] = {}
response: InferenceResponse = {}
async def _run_inference(entry: InferenceEntry) -> None:
model = await model_cache.get(
entry["name"], entry["type"], entry["task"], ttl=settings.model_ttl, **entry["options"]
)
inputs = [payload]View on GitHub (pinned to 199723261c)
Solutions
- Re-upload or re-encode the source image so it has valid non-zero dimensions.
- On the server side, validate the asset file integrity (e.g. re-run metadata extraction) before queuing ML jobs.
- If only a few assets are affected, exclude/regenerate them via the CLIP/duplicate jobs after fixing the file.
Example fix
# before
img = PILImage.open(path)
img.load() # may yield 0x0
# after
img = PILImage.open(path)
if not img.width or not img.height:
raise ValueError(f'bad dimensions {img.size} for {path}') Defensive patterns
Strategy: validation
Validate before calling
from PIL import Image
def valid_image(b: bytes) -> bool:
try:
im = Image.open(io.BytesIO(b)); im.load()
return im.width > 0 and im.height > 0
except Exception:
return False Type guard
def has_valid_dimensions(im) -> bool:
return getattr(im, 'width', 0) > 0 and getattr(im, 'height', 0) > 0 Try / catch
try:
decoded = await run(lambda: decode_pil(image))
except Exception:
raise HTTPException(400, 'Image could not be decoded') Prevention
- Validate uploaded image dimensions before queuing ML jobs.
- Re-run metadata extraction for assets that fail.
When it happens
Trigger: POST /predict with an image file that PIL can decode but which has zero dimension(s) — a corrupt/truncated image header reporting 0x0, or an intentionally crafted edge-case image.
Common situations: Corrupt upload from a flaky mobile sync; partially-written file on disk before the ML request; re-encoded by a faulty transcode/thumbnail pipeline; a 0-byte or header-only file that some decoder tolerates.
Related errors
- Invalid CLIP dimension size: ${dimSize}
- Only images can be edited
- Editing panorama images is not supported
- Editing GIF images is not supported
- Editing SVG images is not supported
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/7ba158ca3dfc78fa.
Report an issue: GitHub.