{"record":{"id":"abd3a81250e78a2c","repo":"invoke-ai/InvokeAI","slug":"free-disk-space-free-space-gb-2f-gb-is-not-en","errorCode":null,"errorMessage":"Free disk space {free_space / GB:.2f} GB is not enough for download of {remaining_bytes / GB:.2f} GB.","messagePattern":"Free disk space (.+?) GB is not enough for download of (.+?) GB\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/download/download_default.py","lineNumber":564,"sourceCode":"        if job.download_path.exists() and resume_from == 0:\n            existing_size = job.download_path.stat().st_size\n            if job.total_bytes > 0 and existing_size == job.total_bytes:\n                job.bytes = existing_size\n                self._signal_job_started(job)\n                self._signal_job_complete(job)\n                return\n            # Existing file does not match expected size; treat as corrupt and restart.\n            self._logger.debug(\n                \"Resume check: existing file size mismatch; deleting and restarting \"\n                f\"path={job.download_path} existing_size={existing_size} expected={job.total_bytes}\"\n            )\n            job.download_path.unlink()\n\n        free_space = disk_usage(job.download_path.parent).free\n        GB = 2**30\n        remaining_bytes = max(job.total_bytes - job.bytes, 0)\n        if free_space < remaining_bytes:\n            raise RuntimeError(\n                f\"Free disk space {free_space / GB:.2f} GB is not enough for download of {remaining_bytes / GB:.2f} GB.\"\n            )\n\n        # Don't clobber an existing file. See commit 82c2c85202f88c6d24ff84710f297cfc6ae174af\n        # for code that instead resumes an interrupted download.\n        if job.download_path.exists() and resume_from == 0:\n            raise OSError(f\"[Errno 17] File {job.download_path} exists\")\n\n        # append \".downloading\" to the path\n        # signal caller that the download is starting. At this point, key fields such as\n        # download_path and total_bytes will be populated. We call it here because the might\n        # discover that the local file is already complete and generate a COMPLETED status.\n        self._signal_job_started(job)\n\n        expected_total = job.total_bytes or job.expected_total_bytes or content_length\n        # \"range not satisfiable\" - local file is at least as large as the remote file\n        if resp.status_code == 416 or (expected_total > 0 and job.bytes >= expected_total):\n            self._logger.info(f\"{job.download_path}: complete file found. Skipping.\")","sourceCodeStart":546,"sourceCodeEnd":582,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/download/download_default.py#L546-L582","documentation":"Before streaming the body, _do_download checks free space on the destination volume (shutil.disk_usage) against the bytes still needed (total_bytes - bytes already downloaded). If free space is less than remaining bytes, RuntimeError is raised so the download aborts before filling the disk. This protects the host from a disk-full condition that could corrupt other application data.","triggerScenarios":"Starting or resuming any download whose remaining size exceeds the free space on the partition containing job.download_path — e.g. an 8 GB model with 5 GB free.","commonSituations":"Large model checkpoints on small volumes/containers with size-limited Docker volumes; downloads directed to /tmp on a small tmpfs; NAS mounts with quotas; multiple concurrent downloads exhausting shared space.","solutions":["Free disk space on the destination volume (delete old models/caches) and resubmit the download.","Point the download at a volume with enough room (change the models directory / dest path in config).","Pre-check space before submitting: compare shutil.disk_usage(dest).free to the expected file size.","Reduce concurrency — pause other queued downloads that share the same volume."],"exampleFix":"# before: submit and hope\nqueue.submit(source, dest)\n\n# after: pre-flight space check\nimport shutil\nsize = expected_size_bytes  # from metadata or HEAD request\nif shutil.disk_usage(dest.parent).free < size:\n    raise SystemExit('not enough space; clean up or change dest')\nqueue.submit(source, dest)","handlingStrategy":"validation","validationCode":"import shutil, requests\ndef has_space(url: str, dest, margin: int = 256 * 2**20) -> bool:\n    h = requests.head(url, allow_redirects=True, timeout=10)\n    size = int(h.headers.get('Content-Length', 0))\n    return shutil.disk_usage(dest if dest.is_dir() else dest.parent).free >= size + margin","typeGuard":null,"tryCatchPattern":"try:\n    queue.submit(source, dest)\nexcept RuntimeError as e:\n    if 'Free disk space' in str(e):\n        cleanup_old_models_or_change_dest()\n        queue.submit(source, alternate_dest_with_space())","preventionTips":["Pre-flight check disk_usage(dest).free against the remote Content-Length before every large download.","Alert/monitor disk usage on the models volume.","Avoid tmpfs/small-container volumes for multi-GB model downloads.","Limit concurrent downloads sharing one volume."],"tags":["filesystem","disk-space","download","resource-exhaustion"],"backgroundTag":"insufficient-disk-space","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}