dotnet/runtime · error · FileNotFoundError

Could not find 'data.tar.*' in {deb_file}.

Error message

Could not find 'data.tar.*' in {deb_file}.

What it means

Raised by extract_deb_file() in install-debs.py when 'ar t <deb_file>' lists archive members and none of them start with 'data.tar'. Every valid .deb file is an ar archive containing at minimum control.tar.* and data.tar.* members. The data.tar member holds the actual filesystem payload that gets extracted into the rootfs.

Source

Thrown at eng/common/cross/install-debs.py:308

    print("All done!")

def extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool):
    """Extract .deb file contents"""

    os.makedirs(extract_dir, exist_ok=True)

    with tempfile.TemporaryDirectory(dir=tmp_dir) as tmp_subdir:
        result = subprocess.run([ar_tool, "t", os.path.abspath(deb_file)], cwd=tmp_subdir, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        tar_filename = None
        for line in result.stdout.decode().splitlines():
            if line.startswith("data.tar"):
                tar_filename = line.strip()
                break

        if not tar_filename:
            raise FileNotFoundError(f"Could not find 'data.tar.*' in {deb_file}.")

        tar_file_path = os.path.join(tmp_subdir, tar_filename)
        print(f"Extracting {tar_filename} from {deb_file}..")

        with open(tar_file_path, "wb") as outfile:
            subprocess.run([ar_tool, "p", os.path.abspath(deb_file), tar_filename], check=True, stdout=outfile, stderr=subprocess.PIPE)

        file_extension = os.path.splitext(tar_file_path)[1].lower()

        if file_extension == ".xz":
            mode = "r:xz"
        elif file_extension == ".gz":
            mode = "r:gz"
        elif file_extension == ".zst":
            # zstd is not supported by standard library yet
            decompressed_tar_path = tar_file_path.replace(".zst", "")
            with open(tar_file_path, "rb") as zst_file, open(decompressed_tar_path, "wb") as decompressed_file:
                dctx = zstandard.ZstdDecompressor()

View on GitHub (pinned to 60108ba66e)

Solutions

  1. Check the actual content of the .deb file with 'file <deb_file>' and 'ar t <deb_file>' to see what members it contains.
  2. Verify the download succeeded by checking the file size and SHA256 against the Packages index.
  3. Retry the download or switch mirrors to rule out a transient corrupt download.
  4. Ensure --artool points to a compatible ar implementation (default 'ar' is GNU ar).
  5. If the file is an HTML error page, fix the mirror URL or suite configuration.

Example fix

# before
result = subprocess.run([ar_tool, "t", os.path.abspath(deb_file)], ...)
tar_filename = None
for line in result.stdout.decode().splitlines():
    if line.startswith("data.tar"):
        tar_filename = line.strip()
        break
if not tar_filename:
    raise FileNotFoundError(f"Could not find 'data.tar.*' in {deb_file}.")

# after - verify file type before extraction
import magic
if not os.path.getsize(deb_file) > 0:
    raise FileNotFoundError(f"Downloaded .deb is empty: {deb_file}")
result = subprocess.run([ar_tool, "t", os.path.abspath(deb_file)], ...)
Defensive patterns

Strategy: validation

Validate before calling

import os, subprocess

def validate_deb_file(deb_file: str, ar_tool: str = "ar") -> bool:
    """Verify a .deb file is a valid ar archive containing data.tar before extraction."""
    if not os.path.exists(deb_file) or os.path.getsize(deb_file) < 100:
        return False
    result = subprocess.run([ar_tool, "t", deb_file], capture_output=True)
    if result.returncode != 0:
        return False
    members = result.stdout.decode().splitlines()
    return any(m.startswith("data.tar") for m in members)

# Usage:
if not validate_deb_file(deb_path, ar_tool):
    raise FileNotFoundError(f"Invalid or corrupt .deb file: {deb_path}")

Type guard

null

Try / catch

try:
    extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool)
except FileNotFoundError as e:
    logging.error(f"Extraction failed, file may be corrupt: {e}")
    os.remove(deb_file)  # clean up corrupt download
    raise

Prevention

When it happens

Trigger: Triggered after successfully downloading a .deb file and running 'ar t' on it, when the output of 'ar t' contains no line starting with 'data.tar'. This can happen if the downloaded file is not actually a .deb (e.g., an HTML error page saved with a .deb extension), if the ar tool produces unexpected output, or if the .deb is corrupt and missing its data archive member.

Common situations: The mirror returned an HTTP 200 with an error page body instead of the real package, the download was truncated leaving a partial/corrupt ar archive, a proxy or CDN served stale/cached content, or the --artool argument points to a tool whose output format differs from GNU/BSD ar (e.g., llvm-ar in some configurations).

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/32c616ece3e4d3d0. Report an issue: GitHub.