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
- Check the actual content of the .deb file with 'file <deb_file>' and 'ar t <deb_file>' to see what members it contains.
- Verify the download succeeded by checking the file size and SHA256 against the Packages index.
- Retry the download or switch mirrors to rule out a transient corrupt download.
- Ensure --artool points to a compatible ar implementation (default 'ar' is GNU ar).
- 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
- Always verify file size after download before processing.
- Use the checksum verification feature (--force-check-gpg) to detect corrupt downloads.
- Run 'file <deb>' to confirm the file type before extraction.
- Log ar tool output on failure for diagnosis.
- Use retry logic for downloads (the script already has max_retries=3).
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
- Invalid Debian version format: {version}
- Unsupported compression format: {file_extension}
- SHA256 mismatch for {url}: expected {checksum}, got {sha256}
- Failed to download {url}, Status Code: {response.status}
- Failed to download {url} after {max_retries} attempts.
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/32c616ece3e4d3d0.
Report an issue: GitHub.