affaan-m/ECC · error · FalError

download length does not match declared size

Error message

download length does not match declared size

What it means

After streaming, download() compares the actual bytes read with the declared Content-Length and raises FalError on a mismatch. This detects truncated or corrupted transfers so a partial file is never promoted to the destination.

Solutions

  1. Retry the download — transient truncation usually succeeds on a second attempt
  2. Check whether a proxy/intermediary is altering the response and bypass it (NO_PROXY / direct connection)
  3. Verify the server's Content-Length with curl -sI and compare with the real byte count
  4. If a specific endpoint consistently misreports length, adjust the client to skip the equality check (not recommended) or fetch without compression

Example fix

# before
# truncated by flaky network
path = download(url, dest)
# after
for attempt in range(3):
    try:
        path = download(url, dest); break
    except FalError as e:
        if 'does not match declared size' not in str(e): raise
        time.sleep(2 ** attempt)
Defensive patterns

Strategy: retry

Validate before calling

# compare declared vs delivered size for your own client
assert int(resp.headers['Content-Length']) == bytes_received

Try / catch

for attempt in range(3):
    try:
        dest = download(url, dest_path)
        break
    except FalError:
        time.sleep(2 ** attempt)
else:
    raise RuntimeError('download kept failing size check')

Prevention

When it happens

Trigger: Connection drops mid-transfer so the server sent fewer bytes than Content-Length declared (truncation); a proxy or CDN alters the body; server sends a wrong Content-Length header (e.g. compressed vs uncompressed mismatch with an interfering intermediary).

Common situations: Flaky Wi-Fi or CI network interruptions during long video downloads; corporate proxy truncating responses; server misreporting length for gzip-encoded content.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/5fd9424f6eab1879. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/taste/falapi.py:715

        with opener.open(req, timeout=300) as resp:
            declared = getattr(resp, "headers", {}).get("Content-Length")
            expected = int(declared) if declared is not None else None
            if expected is not None and not 0 <= expected <= MAX_DOWNLOAD_BYTES:
                raise FalError("download declares an invalid or excessive size")
            with tempfile.NamedTemporaryFile(dir=dest.parent, prefix=".taste-download-",
                                             delete=False) as fh:
                temporary = Path(fh.name)
                total = 0
                while True:
                    chunk = resp.read(min(1024 * 1024, MAX_DOWNLOAD_BYTES - total + 1))
                    if not chunk:
                        break
                    total += len(chunk)
                    if total > MAX_DOWNLOAD_BYTES:
                        raise FalError("download exceeds maximum allowed size")
                    fh.write(chunk)
                if expected is not None and total != expected:
                    raise FalError("download length does not match declared size")
        os.replace(temporary, dest)
        temporary = None
    except FalError:
        raise
    except Exception:
        raise FalError("download failed; existing destination preserved") from None
    finally:
        if temporary is not None:
            temporary.unlink(missing_ok=True)
    return dest


# ---------------------------------------------------------------------------
# dry-run stubs
# ---------------------------------------------------------------------------


def _digest(*parts: Any) -> str:

View on GitHub (pinned to 8321021c54)