{"record":{"id":"c1bd751120a71d67","repo":"dotnet/efcore","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/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/eng/common/cross/install-debs.py#L290-L326","documentation":"Raised as FileNotFoundError by extract_deb_file after `ar t <deb>` lists the archive members and none of them starts with 'data.tar'. Every valid .deb contains debian-binary, control.tar.*, and data.tar.*; absence of data.tar.* means the payload member is missing - the file is truncated, empty, or not actually a .deb (e.g. an HTML error page the mirror served with status 200).","triggerScenarios":"extract_deb_file on a file at tmp_dir/<basename> where `ar t` output contains no 'data.tar' member. Caused by a partial download (connection dropped mid-file), the mirror serving a 200 OK error page, a cache that stored only part of the file, or an ar tool that silently produced no/partial output.","commonSituations":"Disk full so the .deb write was truncated; transparent proxy cached a partial body; mirror returned an error page with HTTP 200 so download_file accepted it; tmp_dir cleared mid-run; wrong --artool that doesn't behave like GNU/BSD ar.","solutions":["Inspect the file: `file <deb_file>` (should report 'Debian binary package') and `ls -l` for a plausible size; `ar t <deb_file>` to see members.","Re-download the offending .deb and clear the tmp_dir cache first to rule out a stale partial file.","Confirm the --artool argument names a real ar implementation (`ar --version`); don't point it at llvm-ar unless that's intended for the format.","Free disk space in tmp_dir if it filled up during the parallel download."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Validate a .deb is well-formed (has data.tar) before extract_deb_file\nimport subprocess, os\n\ndef deb_has_data_tar(deb_file, ar_tool='ar'):\n    if not os.path.exists(deb_file) or os.path.getsize(deb_file) < 100:\n        raise RuntimeError(f\"{deb_file} missing or too small - likely a failed download\")\n    res = subprocess.run([ar_tool, 't', deb_file], capture_output=True, text=True)\n    if res.returncode != 0:\n        raise RuntimeError(f\"{deb_file} is not a valid ar archive: {res.stderr}\")\n    if not any(line.startswith('data.tar') for line in res.stdout.splitlines()):\n        raise RuntimeError(f\"{deb_file} has no data.tar member - corrupt/partial; re-download\")\n    return True","typeGuard":null,"tryCatchPattern":"from pathlib import Path\nimport subprocess\n\nfor deb_file in deb_files:\n    try:\n        extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool)\n    except FileNotFoundError as e:\n        if \"data.tar\" in str(e):\n            # re-download this one .deb once, then retry; abort if it still fails\n            os.remove(deb_file)\n            asyncio.run(download_file(session, url_for(deb_file), deb_file, checksum=checksum_for(deb_file)))\n            extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool)\n        else:\n            raise","preventionTips":["After download, check each .deb size and `file <deb>` reports 'Debian binary package'.","Ensure tmp_dir has free disk space before the parallel download.","Clear the tmp cache between runs so partial files don't linger.","Verify the --artool is GNU/BSD ar before the run."],"tags":["archive","deb","extraction","corruption"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}