{"record":{"id":"1000b01345f11ded","repo":"invoke-ai/InvokeAI","slug":"unable-to-decode-image-image-path-e","errorCode":null,"errorMessage":"Unable to decode image {image_path}: {e}","messagePattern":"Unable to decode image (.+?): (.+?)","errorType":"exception","errorClass":"UnreadableImageError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/image_moves/image_moves_default.py","lineNumber":832,"sourceCode":"                \"\"\"--sql\n                SELECT image_name FROM images\n                WHERE image_name > ?\n                  AND deleted_at IS NULL\n                ORDER BY image_name\n                LIMIT 1;\n                \"\"\",\n                (last_image_name,),\n            )\n            row = cursor.fetchone()\n        return None if row is None else cast(str, row[0])\n\n    def _regenerate_thumbnail(self, image_path: Path, thumbnail_path: Path) -> None:\n        thumbnail_path.parent.mkdir(parents=True, exist_ok=True)\n        try:\n            with Image.open(image_path) as image:\n                thumbnail = make_thumbnail(image)\n        except (UnidentifiedImageError, Image.DecompressionBombError, OSError) as e:\n            raise UnreadableImageError(f\"Unable to decode image {image_path}: {e}\") from e\n        with tempfile.NamedTemporaryFile(\n            dir=thumbnail_path.parent, prefix=f\".{thumbnail_path.name}.\", suffix=\".tmp\", delete=False\n        ) as temp_file:\n            temp_path = Path(temp_file.name)\n        try:\n            thumbnail.save(temp_path, format=\"WEBP\")\n            self._fsync_file(temp_path)\n            os.replace(temp_path, thumbnail_path)\n            self._fsync_file(thumbnail_path)\n            self._fsync_dir(thumbnail_path.parent)\n        finally:\n            temp_path.unlink(missing_ok=True)\n\n    def _mark_missing_intermediate_moved(\n        self,\n        job_id: int,\n        image_name: str,\n        old_path: Path,","sourceCodeStart":814,"sourceCodeEnd":850,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/image_moves/image_moves_default.py#L814-L850","documentation":"_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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: corrupt file aborts the move\n# 0-byte images/x/abc.png present, thumbnail regen fails\n// after: repair or remove corrupt file first\nfrom PIL import Image\nImage.open(\"images/x/abc.png\").verify()  # diagnose\n# if unrecoverable: replace the file, then re-run recovery","handlingStrategy":"try-catch","validationCode":"from pathlib import Path\nfrom PIL import Image, UnidentifiedImageError\ndef image_is_decodable(path: Path) -> bool:\n    if not path.is_file() or path.stat().st_size == 0:\n        return False\n    try:\n        with Image.open(path) as im:\n            im.verify()\n        return True\n    except (UnidentifiedImageError, Image.DecompressionBombError, OSError):\n        return False","typeGuard":"def is_readable_image_file(path: Path) -> bool:\n    return path.is_file() and path.stat().st_size > 0 and path.suffix.lower() in {'.png', '.jpg', '.jpeg', '.webp'}","tryCatchPattern":"from invokeai.app.services.image_moves.image_moves_default import UnreadableImageError\ntry:\n    service.complete_partial_filesystem_moves(job_id)\nexcept UnreadableImageError as e:\n    # e names the undecodable path; quarantine/replace it, then re-run","preventionTips":["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"],"tags":["image-processing","pillow","corrupt-file","thumbnail"],"backgroundTag":"image-decode-failed","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}