invoke-ai/InvokeAI · error · UnreadableImageError
Unable to decode image {image_path}: {e}
Error message
Unable to decode image {image_path}: {e} What it means
_regenerate_thumbnail opens the source image with Pillow to rebuild its WEBP thumbnail. If decoding fails with UnidentifiedImageError, DecompressionBombError, or OSError, it wraps the cause into UnreadableImageError('Unable to decode image {image_path}: {e}'). It means the file at image_path is missing, not a valid image, truncated, or too large to decode safely.
Source
Thrown at invokeai/app/services/image_moves/image_moves_default.py:832
"""--sql
SELECT image_name FROM images
WHERE image_name > ?
AND deleted_at IS NULL
ORDER BY image_name
LIMIT 1;
""",
(last_image_name,),
)
row = cursor.fetchone()
return None if row is None else cast(str, row[0])
def _regenerate_thumbnail(self, image_path: Path, thumbnail_path: Path) -> None:
thumbnail_path.parent.mkdir(parents=True, exist_ok=True)
try:
with Image.open(image_path) as image:
thumbnail = make_thumbnail(image)
except (UnidentifiedImageError, Image.DecompressionBombError, OSError) as e:
raise UnreadableImageError(f"Unable to decode image {image_path}: {e}") from e
with tempfile.NamedTemporaryFile(
dir=thumbnail_path.parent, prefix=f".{thumbnail_path.name}.", suffix=".tmp", delete=False
) as temp_file:
temp_path = Path(temp_file.name)
try:
thumbnail.save(temp_path, format="WEBP")
self._fsync_file(temp_path)
os.replace(temp_path, thumbnail_path)
self._fsync_file(thumbnail_path)
self._fsync_dir(thumbnail_path.parent)
finally:
temp_path.unlink(missing_ok=True)
def _mark_missing_intermediate_moved(
self,
job_id: int,
image_name: str,
old_path: Path,View on GitHub (pinned to 0b6a024f2f)
Solutions
- Try re-opening and re-saving the image (or re-generate it in InvokeAI) to repair or replace the corrupt file.
- Check the file: verify it opens with PIL externally; if it's not a real image, remove or replace it.
- For decompression-bomb errors, raise PIL.Image.MAX_IMAGE_PIXELS if the image is trusted, then retry the move.
- Check file permissions (chmod/chown) if the cause is an OSError from access denial.
- Mark/allow the item to proceed without a thumbnail if the library supports skipping thumbnail regeneration.
Example fix
// before: corrupt file aborts the move
# 0-byte images/x/abc.png present, thumbnail regen fails
// after: repair or remove corrupt file first
from PIL import Image
Image.open("images/x/abc.png").verify() # diagnose
# if unrecoverable: replace the file, then re-run recovery Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path
from PIL import Image, UnidentifiedImageError
def image_is_decodable(path: Path) -> bool:
if not path.is_file() or path.stat().st_size == 0:
return False
try:
with Image.open(path) as im:
im.verify()
return True
except (UnidentifiedImageError, Image.DecompressionBombError, OSError):
return False Type guard
def is_readable_image_file(path: Path) -> bool:
return path.is_file() and path.stat().st_size > 0 and path.suffix.lower() in {'.png', '.jpg', '.jpeg', '.webp'} Try / catch
from invokeai.app.services.image_moves.image_moves_default import UnreadableImageError
try:
service.complete_partial_filesystem_moves(job_id)
except UnreadableImageError as e:
# e names the undecodable path; quarantine/replace it, then re-run Prevention
- Verify image files (PIL verify) after bulk imports or restores
- Remove 0-byte placeholder files before running moves
- Raise PIL.Image.MAX_IMAGE_PIXELS only for trusted large images
- Keep disk health checked; corruption is often a failing-disk symptom
When it happens
Trigger: Completing a filesystem move where the thumbnail must be regenerated: source file is corrupt/truncated (interrupted download/save), is not a real image (renamed file, 0-byte placeholder), exceeds Pillow's decompression-bomb pixel limit, or has permissions preventing read.
Common situations: Interrupted image downloads; corrupted files on failing disks; SVG/text files with image extensions; very large panorama images exceeding PIL.Image.MAX_IMAGE_PIXELS; partially restored backups.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to read image
- Video has no decodable frame
- Video thumbnail not found
- Not an image
- Failed to read image
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/1000b01345f11ded.
Report an issue: GitHub.