{"record":{"id":"32c616ece3e4d3d0","repo":"dotnet/runtime","slug":"could-not-find-data-tar-in-deb-file","errorCode":null,"errorMessage":"Could not find 'data.tar.*' in {deb_file}.","messagePattern":"Could not find 'data\\.tar\\.\\*' in (.+?)\\.","errorType":"exception","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"eng/common/cross/install-debs.py","lineNumber":308,"sourceCode":"\n    print(\"All done!\")\n\ndef extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool):\n    \"\"\"Extract .deb file contents\"\"\"\n\n    os.makedirs(extract_dir, exist_ok=True)\n\n    with tempfile.TemporaryDirectory(dir=tmp_dir) as tmp_subdir:\n        result = subprocess.run([ar_tool, \"t\", os.path.abspath(deb_file)], cwd=tmp_subdir, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n\n        tar_filename = None\n        for line in result.stdout.decode().splitlines():\n            if line.startswith(\"data.tar\"):\n                tar_filename = line.strip()\n                break\n\n        if not tar_filename:\n            raise FileNotFoundError(f\"Could not find 'data.tar.*' in {deb_file}.\")\n\n        tar_file_path = os.path.join(tmp_subdir, tar_filename)\n        print(f\"Extracting {tar_filename} from {deb_file}..\")\n\n        with open(tar_file_path, \"wb\") as outfile:\n            subprocess.run([ar_tool, \"p\", os.path.abspath(deb_file), tar_filename], check=True, stdout=outfile, stderr=subprocess.PIPE)\n\n        file_extension = os.path.splitext(tar_file_path)[1].lower()\n\n        if file_extension == \".xz\":\n            mode = \"r:xz\"\n        elif file_extension == \".gz\":\n            mode = \"r:gz\"\n        elif file_extension == \".zst\":\n            # zstd is not supported by standard library yet\n            decompressed_tar_path = tar_file_path.replace(\".zst\", \"\")\n            with open(tar_file_path, \"rb\") as zst_file, open(decompressed_tar_path, \"wb\") as decompressed_file:\n                dctx = zstandard.ZstdDecompressor()","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/eng/common/cross/install-debs.py#L290-L326","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"# before\nresult = subprocess.run([ar_tool, \"t\", os.path.abspath(deb_file)], ...)\ntar_filename = None\nfor line in result.stdout.decode().splitlines():\n    if line.startswith(\"data.tar\"):\n        tar_filename = line.strip()\n        break\nif not tar_filename:\n    raise FileNotFoundError(f\"Could not find 'data.tar.*' in {deb_file}.\")\n\n# after - verify file type before extraction\nimport magic\nif not os.path.getsize(deb_file) > 0:\n    raise FileNotFoundError(f\"Downloaded .deb is empty: {deb_file}\")\nresult = subprocess.run([ar_tool, \"t\", os.path.abspath(deb_file)], ...)","handlingStrategy":"validation","validationCode":"import os, subprocess\n\ndef validate_deb_file(deb_file: str, ar_tool: str = \"ar\") -> bool:\n    \"\"\"Verify a .deb file is a valid ar archive containing data.tar before extraction.\"\"\"\n    if not os.path.exists(deb_file) or os.path.getsize(deb_file) < 100:\n        return False\n    result = subprocess.run([ar_tool, \"t\", deb_file], capture_output=True)\n    if result.returncode != 0:\n        return False\n    members = result.stdout.decode().splitlines()\n    return any(m.startswith(\"data.tar\") for m in members)\n\n# Usage:\nif not validate_deb_file(deb_path, ar_tool):\n    raise FileNotFoundError(f\"Invalid or corrupt .deb file: {deb_path}\")","typeGuard":"null","tryCatchPattern":"try:\n    extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool)\nexcept FileNotFoundError as e:\n    logging.error(f\"Extraction failed, file may be corrupt: {e}\")\n    os.remove(deb_file)  # clean up corrupt download\n    raise","preventionTips":["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)."],"tags":["debian","packaging","rootfs","ar-archive","download"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}