dotnet/aspnetcore · error · FileNotFoundError
Could not find 'data.tar.*' in {deb_file}.
Error message
Could not find 'data.tar.*' in {deb_file}. What it means
extract_deb_file runs 'ar t <deb>' to list the archive members and looks for one starting with 'data.tar'. If none is found, it raises FileNotFoundError. A well-formed .deb always contains control.tar.* and data.tar.*; a missing data.tar means the .deb is truncated, corrupt, or not actually a .deb (e.g., an HTML error page saved with a .deb name).
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 294cab2f9b)
Solutions
- Inspect the offending .deb file with 'file <deb>' and 'ar t <deb>' — if it is HTML or empty, the download is the real problem.
- Re-run with a clean mirror; transient corruption usually clears on re-download.
- Ensure the --artool (default 'ar') is GNU binutils ar; llvm-ar may format member listings differently.
- Delete the tmp_dir before re-running so stale partial files do not mask fresh downloads.
Example fix
# before python3 install-debs.py --artool llvm-ar --mirror http://broken/ ... # Could not find 'data.tar.*' in /tmp/.../libc6.deb # diagnose file /tmp/.../libc6.deb # -> HTML document text # after python3 install-debs.py --mirror http://deb.debian.org/debian ...
Defensive patterns
Strategy: validation
Validate before calling
# Validate the .deb structure before passing to extract_deb_file
import subprocess, os
def deb_has_data_tar(path: str, ar: str = 'ar') -> bool:
r = subprocess.run([ar, 't', os.path.abspath(path)], capture_output=True)
return any(line.startswith('data.tar') for line in r.stdout.decode().splitlines())
if not deb_has_data_tar(deb_file):
raise SystemExit(f'{deb_file} is not a valid .deb (no data.tar); re-download') Try / catch
try:
extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool)
except FileNotFoundError as e:
if 'data.tar' in str(e):
print(f'{deb_file} corrupt; deleting and skipping')
os.remove(deb_file)
continue
raise Prevention
- Run 'file <deb>' on downloaded .debs in CI to catch HTML/empty responses.
- Ensure --artool is GNU binutils ar.
- Delete tmp_dir before each build to avoid stale partial files.
- Verify download_file raises on non-200 so error pages never reach disk.
When it happens
Trigger: Reached during install_packages after the parallel download. For each resolved package, 'ar t' is run on the downloaded file; the stdout is scanned line-by-line for a 'data.tar' prefix. A 404 HTML page or partial download saved to the .deb path produces no matching line and raises.
Common situations: download_file wrote a non-200 response body to disk (note: download_file raises on non-200, but a transparent proxy could still serve a 200 with an error body); the .deb was truncated by a network interruption that did not trigger a ClientError; the ar tool is misconfigured (e.g., llvm-ar behaving differently) and produces unexpected output; the file was overwritten by a concurrent download.
Related errors
- 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.
- SHA256 mismatch for {path}: expected {packages_sha}, got {sh
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/fb67956123cf30eb.
Report an issue: GitHub.