invoke-ai/InvokeAI · error · ImageFileSaveException

ImageFileSaveException

Error message

ImageFileSaveException

What it means

ImageFilesDisk.save() failed while writing a PIL image (and/or its thumbnail) to disk — e.g. an OSError from mkdir/write — after cleaning up any partially written files and evicting cache entries. The original exception is chained as the cause. Callers of the save path (including _get_png_size consumers) see this uniform wrapper instead of the raw I/O error.

Source

Thrown at invokeai/app/services/image_files/image_files_disk.py:198

                **save_options,
            )

            thumbnail_image.save(thumbnail_path)

            self.__set_cache(image_path, image)
            self.__set_cache(thumbnail_path, thumbnail_image)
        except Exception as e:
            # A thumbnail failure must not leave a full-size image with no thumbnail. The
            # names are normally new, but preserve any pre-existing files when save() is
            # used to overwrite an existing image.
            for path, existed in ((image_path, image_existed), (thumbnail_path, thumbnail_existed)):
                if path is not None and not existed:
                    try:
                        path.unlink(missing_ok=True)
                    except OSError:
                        pass
            self.evict_cache_paths([path for path in (image_path, thumbnail_path) if path is not None])
            raise ImageFileSaveException from e

    def delete(self, image_name: str, image_subfolder: str = "") -> None:
        token = self.stage_delete(image_name, image_subfolder)
        self.commit_delete(token)

    def stage_delete(self, image_name: str, image_subfolder: str = "") -> _StagedDelete:
        candidates = [
            self.get_path(image_name, image_subfolder=image_subfolder),
            self.get_path(image_name, thumbnail=True, image_subfolder=image_subfolder),
        ]
        staging_dir = Path(tempfile.mkdtemp(prefix=".delete_", dir=self.__output_folder))
        staged: list[tuple[Path, Path]] = []
        try:
            with open(staging_dir / "manifest.json", "w", encoding="utf-8") as manifest:
                manifest.write(json.dumps({"image_name": image_name, "image_subfolder": image_subfolder}))
                manifest.flush()
                os.fsync(manifest.fileno())
            for index, source in enumerate(candidates):

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Inspect the chained cause (__cause__) to identify the precise OSError (disk full, permission denied, etc.)
  2. Free disk space on the output volume if the cause is ENOSPC
  3. Fix permissions/ownership on the output folder so the service process can write
  4. Ensure the output folder is on a writable, non-read-only mount

Example fix

// before
services.images.save(image, image_name)  # ImageFileSaveException: [Errno 28] No space left
// after
# fix host/volume first, then retry
$ df -h /invokeai/outputs && chmod u+rwX /invokeai/outputs
services.images.save(image, image_name)
Defensive patterns

Strategy: validation

Validate before calling

import shutil
from pathlib import Path
out = Path(services.images.get_path("__probe__")).parent
out.mkdir(parents=True, exist_ok=True)
probe = out / ".write_probe"
probe.write_bytes(b"")
probe.unlink()
if shutil.disk_usage(out).free < 100 * 1024 * 1024:
    raise RuntimeError("Output volume low on disk")

Try / catch

try:
    services.images.save(image, image_name)
except ImageFileSaveException as e:
    logger.error(f"image save failed: {e.__cause__}")
    raise HTTPException(500, "Could not persist image; check disk space/permissions")

Prevention

When it happens

Trigger: Calling save(image, image_name) when the destination directory cannot be created or written: disk full, permission denied on the output folder, path too long, or an I/O error during PIL save or thumbnail write.

Common situations: Output volume out of disk space; wrong ownership/permissions after running the app as different users (e.g. Docker volume permission mismatch); read-only mount; subfolder names colliding with files on the filesystem.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/3d570e7b2d4af3a3. Report an issue: GitHub.