{"record":{"id":"1bebc100c3dc9250","repo":"affaan-m/ECC","slug":"download-failed-existing-destination-preserved","errorCode":null,"errorMessage":"download failed; existing destination preserved","messagePattern":"download failed; existing destination preserved","errorType":"exception","errorClass":"FalError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/falapi.py","lineNumber":721,"sourceCode":"                                             delete=False) as fh:\n                temporary = Path(fh.name)\n                total = 0\n                while True:\n                    chunk = resp.read(min(1024 * 1024, MAX_DOWNLOAD_BYTES - total + 1))\n                    if not chunk:\n                        break\n                    total += len(chunk)\n                    if total > MAX_DOWNLOAD_BYTES:\n                        raise FalError(\"download exceeds maximum allowed size\")\n                    fh.write(chunk)\n                if expected is not None and total != expected:\n                    raise FalError(\"download length does not match declared size\")\n        os.replace(temporary, dest)\n        temporary = None\n    except FalError:\n        raise\n    except Exception:\n        raise FalError(\"download failed; existing destination preserved\") from None\n    finally:\n        if temporary is not None:\n            temporary.unlink(missing_ok=True)\n    return dest\n\n\n# ---------------------------------------------------------------------------\n# dry-run stubs\n# ---------------------------------------------------------------------------\n\n\ndef _digest(*parts: Any) -> str:\n    h = hashlib.sha256(\"|\".join(str(p) for p in parts).encode(\"utf-8\"))\n    return h.hexdigest()[:12]\n\n\ndef _stub_from_schema(schema: dict) -> dict:\n    \"\"\"Build a stub object with the same keys and types as ``schema``.\"\"\"","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/falapi.py#L703-L739","documentation":"download() wraps its whole download loop in a broad except: any non-FalError exception (network I/O error, DNS failure, timeout, disk full, permission error) is converted to FalError with the message 'download failed; existing destination preserved'. The handler re-raises FalError unchanged, and a finally block unlinks the temp file, so a failed download never clobbers a pre-existing destination file.","triggerScenarios":"Any exception during download(url, dest) other than the explicit size/limit checks: socket timeouts, connection reset, HTTP errors surfaced as exceptions, unwritable temp directory, disk-full during fh.write, or os.replace failing.","commonSituations":"Server outage or 5xx from the CDN; no internet/DNS in a container; full disk when saving large video files; read-only working directory; wrong destination path (parent missing).","solutions":["Check that the destination directory exists and is writable; create the parent with Path(dest).parent.mkdir(parents=True, exist_ok=True).","Test connectivity to the fal.ai/CDN host (curl -I the URL).","Free disk space if the drive is full — large media downloads commonly hit ENOSPC.","Retry with backoff; transient network faults are the dominant cause.","Inspect the suppressed underlying exception by reproducing the fetch outside download() (e.g. urllib) to see the real cause, since the handler hides it with `from None`."],"exampleFix":"// before\ndest.parent.mkdir(parents=True, exist_ok=True)  # missing\napi.download(url, dest)\n\n// after\ndest = Path(dest)\ndest.parent.mkdir(parents=True, exist_ok=True)\ntry:\n    api.download(url, dest)\nexcept api.FalError as e:\n    print('download failed, previous file kept:', e)","handlingStrategy":"try-catch","validationCode":"from pathlib import Path\nimport shutil\n\ndef can_download_to(dest):\n    dest = Path(dest)\n    dest.parent.mkdir(parents=True, exist_ok=True)\n    if not os.access(dest.parent, os.W_OK):\n        return False\n    return shutil.disk_usage(dest.parent).free > MIN_FREE_BYTES","typeGuard":null,"tryCatchPattern":"try:\n    api.download(url, dest)\nexcept api.FalError as e:\n    log.warning('download failed, existing file kept: %s', e)\n    # fall back to cached dest or re-raise","preventionTips":["Ensure the destination parent directory exists and is writable before calling.","Check free disk space before large media downloads.","Verify connectivity to the host with a cheap HEAD request first.","Remember the API hides the root cause (from None) — reproduce with curl/urllib when diagnosing."],"tags":["network","download","io","python"],"backgroundTag":"http-request-failed","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}