pypa/pip · error · ValueError

Unknown format for %r

Error message

Unknown format for %r

What it means

Raised by unarchive() when the archive format cannot be inferred and the caller did not pass an explicit format= argument. The extension is checked against ('.zip', '.tar.gz', '.tgz', '.tar.bz2', '.tbz', '.tar', '.whl'); if none match, ValueError 'Unknown format for %r' is raised.

Source

Thrown at src/pip/_vendor/distlib/util.py:1271

        check_path(member.linkname, base=link_base)

    dest_dir = os.path.abspath(dest_dir)
    plen = len(dest_dir)
    archive = None
    if format is None:
        if archive_filename.endswith(('.zip', '.whl')):
            format = 'zip'
        elif archive_filename.endswith(('.tar.gz', '.tgz')):
            format = 'tgz'
            mode = 'r:gz'
        elif archive_filename.endswith(('.tar.bz2', '.tbz')):
            format = 'tbz'
            mode = 'r:bz2'
        elif archive_filename.endswith('.tar'):
            format = 'tar'
            mode = 'r'
        else:  # pragma: no cover
            raise ValueError('Unknown format for %r' % archive_filename)
    try:
        if format == 'zip':
            archive = ZipFile(archive_filename, 'r')
            if check:
                names = archive.namelist()
                for name in names:
                    check_path(name)
        else:
            archive = tarfile.open(archive_filename, mode)
            if check:
                for member in archive.getmembers():
                    check_path(member.name)
                    check_link(member)
        if format != 'zip' and sys.version_info[0] < 3:
            # See Python issue 17153. If the dest path contains Unicode,
            # tarfile extraction fails on Python 2.x if a member path name
            # contains non-ASCII characters - it leads to an implicit
            # bytes -> unicode conversion using ASCII to decode.

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Pass the format explicitly: unarchive(path, dest, format='zip') or format='tgz' / 'tbz' / 'tar'.
  2. Rename the file to a recognized extension before calling.
  3. For .tar.xz/.tar.zst, extract with Python's tarfile.open(path, 'r:xz'/'r:zst') directly instead of unarchive().

Example fix

// before
unarchive('snapshot', dest)  # no extension
// after
unarchive('snapshot', dest, format='tgz')
Defensive patterns

Strategy: validation

Validate before calling

import os
KNOWN = ('.zip', '.tar.gz', '.tgz', '.tar.bz2', '.tbz', '.tar', '.whl')
def infer_format(path):
    low = path.lower()
    for ext in KNOWN:
        if low.endswith(ext):
            return {'zip':'zip','.whl':'zip','.tgz':'tgz','.tar.gz':'tgz','.tbz':'tbz','.tar.bz2':'tbz','.tar':'tar'}[ext]
    return None

def safe_unarchive(path, dest, **kw):
    fmt = kw.pop('format', None) or infer_format(path)
    if fmt is None:
        raise ValueError('cannot infer archive format for %r; pass format=' % path)
    from distlib.util import unarchive
    return unarchive(path, dest, format=fmt, **kw)

Try / catch

from distlib.util import unarchive
try:
    unarchive(path, dest)
except ValueError as e:
    if 'Unknown format' in str(e):
        unarchive(path, dest, format='tgz')  # pick correct format explicitly
    else:
        raise

Prevention

When it happens

Trigger: unarchive('data.xz'), unarchive('snapshot'), unarchive('file.tar.xz'), or calling unarchive on a path with no recognized extension while passing format=None.

Common situations: Renaming archives, downloading files whose extension was stripped, or newer compression formats (.tar.xz, .tar.zst) not in the recognized set.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/c7dd3c078c17e2a0.json. Report an issue: GitHub.