{"record":{"id":"4d3e754141e8e688","repo":"dotnet/yarp","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/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/eng/common/cross/install-debs.py#L290-L326","documentation":"This FileNotFoundError is raised in extract_deb_file after running 'ar t <deb_file>' to list the archive's member files. The code scans stdout lines for one starting with 'data.tar' (the member that holds the actual package payload). If no such member is found, the .deb file does not contain a data.tar archive -- meaning it is not a valid Debian package, is corrupted, was truncated during download, or is actually a different file type (e.g. an HTML error page saved with a .deb extension).","triggerScenarios":"extract_deb_file (lines 293-308) runs subprocess.run([ar_tool, 't', deb_file]) and iterates result.stdout lines looking for one starting with 'data.tar'. If none is found, tar_filename stays None and the exception fires. This occurs when: the downloaded .deb is an HTML error page (404/403 page saved as .deb) because the download status wasn't checked properly; the file was truncated; the file is a .udeb or other variant with a different internal structure; the ar_tool ('ar' or 'llvm-ar') failed silently or returned unexpected output format; the file is genuinely corrupt.","commonSituations":"A 404 or 403 response body was saved as a .deb file because the download path returned non-200 but the error wasn't propagated (related to error 103's retry bug); the .deb was partially downloaded (network interruption, disk full); the file is actually a .rpm, .tar, or HTML page mislabeled; the ar tool path is wrong or ar is not installed, causing 'ar t' to produce empty stdout (though check=True should catch non-zero exit); using llvm-ar which may output member names in a different format; the .deb uses a non-standard archive format.","solutions":["Check the file type: run file <deb_file> to confirm it is actually a Debian binary package (should report 'Debian binary package').","Inspect the file size -- if it is suspiciously small (a few KB), it is likely an error page, not a real package.","Manually run: ar t <deb_file> to see what members are listed and confirm the ar tool works.","Verify the download succeeded -- check for a SHA256 mismatch (error 102) that may have been logged but the file still written.","Re-download the specific .deb file and verify its integrity before extraction.","Ensure the correct ar tool is available: which ar (or specify --artool llvm-ar explicitly).","Add a pre-extraction check: verify the file starts with the '!<arch>' magic bytes that identify ar archives."],"exampleFix":"# before -- assumes data.tar always exists in the .deb\nif not tar_filename:\n    raise FileNotFoundError(f\"Could not find 'data.tar.*' in {deb_file}.\")\n\n# after -- verify the file is a valid .deb before attempting extraction\nwith open(deb_file, 'rb') as f:\n    magic = f.read(8)\nif magic != b'!<arch>':\n    raise FileNotFoundError(\n        f\"{deb_file} is not a valid Debian archive (bad magic: {magic!r}). \"\n        f\"The download may have saved an error page.\")\nif not tar_filename:\n    raise FileNotFoundError(f\"Could not find 'data.tar.*' in {deb_file}.\")","handlingStrategy":"validation","validationCode":"# Pre-check: verify the file is a valid ar archive before extraction.\nimport os\n_DEB_MAGIC = b'!<arch>'\ndef is_valid_deb(path):\n    if not os.path.exists(path) or os.path.getsize(path) < 100:\n        return False\n    with open(path, 'rb') as f:\n        return f.read(8) == _DEB_MAGIC","typeGuard":"# Check ar archive magic bytes\ndef is_ar_archive(path):\n    try:\n        with open(path, 'rb') as f:\n            return f.read(8) == b'!<arch>'\n    except (OSError, IOError):\n        return False","tryCatchPattern":"# Wrap extraction and skip corrupt .deb files\ntry:\n    extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool)\nexcept FileNotFoundError as e:\n    if 'data.tar' in str(e):\n        print(f\"WARNING: {deb_file} has no data.tar member. File may be corrupt. Skipping.\")\n        continue\n    raise","preventionTips":["Verify each .deb file's magic bytes ('!<arch>') before attempting extraction.","Check file sizes after download -- a .deb that is only a few KB is likely an error page.","Ensure downloads are validated (SHA256 check) before extraction so corrupt files are caught earlier.","Verify the ar tool is installed and on PATH before running the batch extraction.","Log the 'ar t' output for each .deb to diagnose which file is problematic."],"tags":["python","debian","deb","ar","extraction","file-format","apt"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}