From 7e74fa767c41f3f3068f12aea80ec53cb2b55fa4 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Tue, 30 Jun 2026 22:32:51 -0400 Subject: [PATCH] =?UTF-8?q?fix(agent):=20load=20huge=20images=20=E2=80=94?= =?UTF-8?q?=20disable=20PIL=20decompression-bomb=20guard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trusted local library, not an upload surface, so a legitimately large image (90–95M px, operator-flagged) must load. PIL only WARNS at the 89M-px default but RAISES DecompressionBombError at ~179M px, which would fail those jobs. Set Image.MAX_IMAGE_PIXELS = None. (The agent works off individual extracted files — curator's archive_extractor unpacks zip/cbz/rar/7z at import — so this is about big single images, not archives.) Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Ttrj5P7upUTueSfoJcxEqa --- agent/fc_agent/app.py | 2 +- agent/fc_agent/media.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/agent/fc_agent/app.py b/agent/fc_agent/app.py index 1f001ca..5505e56 100644 --- a/agent/fc_agent/app.py +++ b/agent/fc_agent/app.py @@ -15,7 +15,7 @@ from .worker import Worker # Bump on every agent change. The page embeds this and /status reports it; the UI # warns to reload when they differ — so a stale browser-cached page can't be # mistaken for "the new image didn't deploy". (Belt-and-braces with no-store.) -VERSION = "2026-06-30.7 · ubuntu24.04-py312-cuda12.9" +VERSION = "2026-06-30.8 · ubuntu24.04-py312 · big-images" logbuf.install() cfg = Config.from_env() diff --git a/agent/fc_agent/media.py b/agent/fc_agent/media.py index 24a9f6e..29cbc24 100644 --- a/agent/fc_agent/media.py +++ b/agent/fc_agent/media.py @@ -13,6 +13,13 @@ from PIL import Image, ImageFile # and would otherwise fail the job 3× then error (operator-flagged 2026-06-30). ImageFile.LOAD_TRUNCATED_IMAGES = True +# Disable PIL's decompression-bomb guard: this is a TRUSTED local library, not an +# untrusted upload surface, so a legitimately huge image (high-res scans/prints, +# 90M+ pixels) must load. The default 89M-pixel limit only WARNS, but PIL raises +# DecompressionBombError at 2× (~179M px) — which would fail those jobs outright +# (operator-flagged 2026-06-30, images of 90–95M px). +Image.MAX_IMAGE_PIXELS = None + def is_video(mime: str) -> bool: return bool(mime) and (mime.startswith("video/") or mime in {"image/gif"})