roboflow/supervision · error · ValueError

Downloaded asset {filename} failed MD5 verification.

Error message

Downloaded asset {filename} failed MD5 verification.

What it means

Raised by the supervision asset downloader when a downloaded file's MD5 hash does not match the expected hash recorded in MEDIA_ASSETS, after one automatic retry. This protects against corrupted or truncated downloads (flaky networks, interrupted connections) so downstream code never consumes a broken asset.

Source

Thrown at src/supervision/assets/downloader.py:71

    _download_asset(filename, destination)

    if is_md5_hash_matching(check_target, original_md5_hash):
        return

    logger.warning("File corrupted. Re-downloading...")
    os.remove(check_target)

    if retry_on_mismatch:
        _download_verified_asset(
            filename=filename,
            original_md5_hash=original_md5_hash,
            destination=destination,
            check_target=check_target,
            retry_on_mismatch=False,
        )
        return

    raise ValueError(f"Downloaded asset {filename!r} failed MD5 verification.")


def download_assets(
    asset_name: Assets | str,
    directory: str | Path | None = None,
) -> str:
    """
    Download a specified asset if it doesn't already exist or is corrupted.

    Args:
        asset_name: The name or type of the asset to be downloaded.
        directory: Optional output directory. Defaults to the current working
            directory for backward compatibility.

    Returns:
        The downloaded asset path. When `directory` is omitted, this preserves
        the historical filename-only return value.

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Delete the partially downloaded file in the target directory and call download_assets() again fresh.
  2. Check network/proxy environment (HTTP_PROXY/HTTPS_PROXY) — ensure nothing is rewriting the response body.
  3. Verify the destination directory is writable and has disk space.
  4. If it persists, download the asset manually and place it at the expected path with the correct name.

Example fix

// before
download_assets(Assets.ENCODED_VIDEO, directory="assets")  # MD5 mismatch

// after
# clear the corrupted file, then re-download
if (Path("assets") / "cctv-1080p.mp4").exists():
    (Path("assets") / "cctv-1080p.mp4").unlink()
download_assets(Assets.ENCODED_VIDEO, directory="assets")
Defensive patterns

Strategy: retry

Validate before calling

target = Path(directory or ".") / filename
if target.exists():
    target.unlink()  # clear corrupted partial download
path = download_assets(asset, directory=directory)

Try / catch

for attempt in range(3):
    try:
        path = download_assets(asset, directory=directory)
        break
    except ValueError as e:
        if "MD5 verification" not in str(e) or attempt == 2:
            raise
        for f in Path(directory).glob("*"):
            f.unlink()  # remove corrupt files before retrying

Prevention

When it happens

Trigger: Calling download_assets(...) where the download completes but the file bytes hash differently — e.g. a proxy injecting an error page, a partially-written file, or a host whose mirror serves modified content. Note the downloader retries once (retry_on_mismatch) before raising.

Common situations: CI runners behind corporate proxies that alter responses; interrupted connections on slow networks; disk full causing truncated writes; the asset URL being repointed to different content.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/99eb22f3e3bbaa10. Report an issue: GitHub.