{"record":{"id":"b40dee541f891d35","repo":"affaan-m/ECC","slug":"download-exceeds-maximum-allowed-size-falapi","errorCode":null,"errorMessage":"download exceeds maximum allowed size","messagePattern":"download exceeds maximum allowed size","errorType":"exception","errorClass":"FalError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/taste/falapi.py","lineNumber":712,"sourceCode":"    opener = urllib.request.build_opener(_SafeRedirect())\n    temporary = None\n    try:\n        with opener.open(req, timeout=300) as resp:\n            declared = getattr(resp, \"headers\", {}).get(\"Content-Length\")\n            expected = int(declared) if declared is not None else None\n            if expected is not None and not 0 <= expected <= MAX_DOWNLOAD_BYTES:\n                raise FalError(\"download declares an invalid or excessive size\")\n            with tempfile.NamedTemporaryFile(dir=dest.parent, prefix=\".taste-download-\",\n                                             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# ---------------------------------------------------------------------------","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/taste/falapi.py#L694-L730","documentation":"While streaming the response body, download() tracks the total bytes read and aborts with FalError if it exceeds MAX_DOWNLOAD_BYTES. This guards against servers that lie about (or omit) Content-Length and keep sending data, so the temp file cannot grow unbounded.","triggerScenarios":"A server omits Content-Length (so the declared-size check is skipped) and streams more than MAX_DOWNLOAD_BYTES; a server sends fewer bytes in the header than it actually writes; a redirect or proxy duplicates/loops the body stream.","commonSituations":"Chunked-transfer responses without a declared length; downloading a bundle bigger than the limit where the header check never fired; malicious or misconfigured endpoint streaming endlessly.","solutions":["Increase MAX_DOWNLOAD_BYTES if the asset legitimately needs more space","Verify the asset's true size beforehand with a HEAD request","Download with your own client if you need different streaming limits","Retry against a direct fal.media URL, bypassing any proxy that might mangle the stream"],"exampleFix":"// before\nwhile True:\n    chunk = resp.read(1024 * 1024)\n// after\n# raise MAX_DOWNLOAD_BYTES in falapi.py first, or pre-check:\nhead = requests.head(url); size = int(head.headers.get('Content-Length', 0))\nassert 0 < size <= MAX_DOWNLOAD_BYTES","handlingStrategy":"validation","validationCode":"size = int(urllib.request.urlopen(urllib.request.Request(url, method='HEAD')).headers.get('Content-Length', 0))\nassert size <= MAX_DOWNLOAD_BYTES","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-check asset size with a HEAD request, especially when no Content-Length will be sent","Increase MAX_DOWNLOAD_BYTES if you regularly download large videos","Bypass misbehaving proxies that can duplicate or extend streams","Monitor pipeline downloads for assets that grow between versions"],"tags":["download","size-limit","http","streaming"],"backgroundTag":"file-size-limit-exceeded","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"}