dotnet/yarp · error · ValueError

Unsupported compression format: {file_extension}

Error message

Unsupported compression format: {file_extension}

What it means

This ValueError is raised in extract_deb_file after extracting the data.tar member from the .deb archive and inspecting its file extension. The code supports three compression formats: .xz (mode r:xz), .gz (mode r:gz), and .zst (manual decompression via zstandard). Any other extension triggers this error. Debian packages can theoretically use other compressions (.bz2, .lzma, .tar with no compression), and some distributions or package builders may produce .deb files with these less common formats.

Source

Thrown at eng/common/cross/install-debs.py:332

            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()
                dctx.copy_stream(zst_file, decompressed_file)

            tar_file_path = decompressed_tar_path
            mode = "r"
        else:
            raise ValueError(f"Unsupported compression format: {file_extension}")

        with tarfile.open(tar_file_path, mode) as tar:
            tar.extractall(path=extract_dir, filter=_rootfs_extraction_filter)

def _rootfs_extraction_filter(member, dest_path):
    """Tarfile extraction filter based on the 'data' filter that additionally
    rewrites absolute-target symlinks/hardlinks into rootfs-relative paths.
    """
    if (member.issym() or member.islnk()) and os.path.isabs(member.linkname):
        link_dir = os.path.dirname(member.name)
        new_linkname = os.path.relpath(member.linkname.lstrip('/'),
                                       start=link_dir or '.')
        member = member.replace(linkname=new_linkname, deep=False)
    return tarfile.data_filter(member, dest_path)

def finalize_setup(rootfsdir):
    lib_dir = os.path.join(rootfsdir, 'lib')
    usr_lib_dir = os.path.join(rootfsdir, 'usr', 'lib')

View on GitHub (pinned to bd11867bee)

Solutions

  1. Inspect the actual tar filename printed at line 311 ('Extracting {tar_filename} from {deb_file}') to see the exact extension.
  2. If the format is .bz2, add mode 'r:bz2' support (Python's tarfile supports it natively).
  3. If the format is .lzma, add mode 'r:lzma' support (also natively supported by tarfile).
  4. If the file is uncompressed (data.tar with extension '.tar'), add a branch for '.tar' that uses mode 'r'.
  5. Handle the double-extension case: instead of os.path.splitext (which only strips the last extension), check if the basename starts with 'data.tar' and determine compression from the full suffix.
  6. If a specific package uses an unsupported format, repackage it or find an alternative version with a supported compression.

Example fix

# before -- only .xz, .gz, .zst are supported
if file_extension == ".xz":
    mode = "r:xz"
elif file_extension == ".gz":
    mode = "r:gz"
elif file_extension == ".zst":
    ...
else:
    raise ValueError(f"Unsupported compression format: {file_extension}")

# after -- add .bz2, .lzma, and uncompressed .tar support
if file_extension == ".xz":
    mode = "r:xz"
elif file_extension == ".gz":
    mode = "r:gz"
elif file_extension == ".bz2":
    mode = "r:bz2"
elif file_extension == ".lzma":
    mode = "r:lzma"
elif file_extension == ".tar":
    mode = "r"
elif file_extension == ".zst":
    ...
else:
    raise ValueError(f"Unsupported compression format: {file_extension}")
Defensive patterns

Strategy: fallback

Validate before calling

# Pre-check: determine the compression type from the member filename before extraction.
_SUPPORTED_EXTENSIONS = {'.xz', '.gz', '.zst', '.bz2', '.lzma', '.tar'}
def is_supported_compression(tar_filename):
    ext = os.path.splitext(tar_filename)[1].lower()
    return ext in _SUPPORTED_EXTENSIONS

Type guard

# Check extension against supported set
def get_tar_mode(tar_filename):
    ext = os.path.splitext(tar_filename)[1].lower()
    modes = {'.xz': 'r:xz', '.gz': 'r:gz', '.bz2': 'r:bz2', '.lzma': 'r:lzma', '.tar': 'r'}
    return modes.get(ext)

# Usage (zst handled separately due to manual decompression):
mode = get_tar_mode(tar_filename)
if mode is None and not tar_filename.endswith('.zst'):
    raise ValueError(f"Unsupported compression: {ext}")

Try / catch

# Catch unsupported compression and attempt fallback or skip
try:
    extract_deb_file(deb_file, tmp_dir, extract_dir, ar_tool)
except ValueError as e:
    if 'Unsupported compression' in str(e):
        print(f"WARNING: {deb_file} uses unsupported compression.")
        import shutil
        if shutil.which('dpkg-deb'):
            subprocess.run(['dpkg-deb', '-x', deb_file, extract_dir], check=True)
        else:
            print(f"Skipping {deb_file} -- no extraction tool available.")
    else:
        raise

Prevention

When it happens

Trigger: extract_deb_file (line 316) calls os.path.splitext on the extracted data.tar filename to get file_extension, then matches it against .xz, .gz, .zst. The ValueError fires for any other extension. This occurs when: a package uses bz2 compression (data.tar.bz2); a package uses lzma compression (data.tar.lzma); the tar file has no compression extension (data.tar, extension is '.tar' -- note splitext returns '.tar' not empty); the filename has an unexpected extension due to naming conventions in a specific distribution; a non-standard packaging tool produced an unusual compression.

Common situations: Downloading packages from a distribution that defaults to bz2 or lzma compression for small packages; processing older .deb files that predate xz as the default; the filename has a double extension or unusual naming causing splitext to return an unexpected value; the ar member listing includes a versioned or suffixed name; encountering a .udeb (micro-deb) with different compression; a package from a custom-built or third-party repository using non-standard compression.

Related errors


AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13). Data as JSON: /api/errors/b24ffa86964e4084. Report an issue: GitHub.