ungoogled-software/ungoogled-chromium · error · FileExistsError

Temporary unpacking directory already exists: %s

Error message

Temporary unpacking directory already exists: %s

What it means

_extract_tar_with_7z checks before extracting whether output_dir/relative_to already exists; if it does, the two-pass 7z streaming extraction would collide with leftover files, so it raises FileExistsError. This is a pre-flight sanity check to avoid merging old and new extraction output.

Source

Thrown at utils/_extraction.py:95

    if relative_to is None:
        return
    relative_root = unpack_root / relative_to
    if not relative_root.is_dir():
        get_logger().error('Could not find relative_to directory in extracted files: %s',
                           relative_to)
        raise FileNotFoundError()
    for src_path in relative_root.iterdir():
        dest_path = unpack_root / src_path.name
        src_path.rename(dest_path)
    relative_root.rmdir()


def _extract_tar_with_7z(binary, archive_path, output_dir, relative_to):
    get_logger().debug('Using 7-zip extractor')
    if not relative_to is None and (output_dir / relative_to).exists():
        get_logger().error('Temporary unpacking directory already exists: %s',
                           output_dir / relative_to)
        raise FileExistsError()
    cmd1 = (binary, 'x', str(archive_path), '-so')
    cmd2 = (binary, 'x', '-si', '-snld', '-aoa', '-ttar', f'-o{str(output_dir)}')
    get_logger().debug('7z command line: %s | %s', ' '.join(cmd1), ' '.join(cmd2))

    proc1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE) #pylint: disable=consider-using-with
    proc2 = subprocess.Popen(cmd2, stdin=proc1.stdout, stdout=subprocess.PIPE) #pylint: disable=consider-using-with
    proc1.stdout.close()
    (stdout_data, stderr_data) = proc2.communicate()
    if proc2.returncode != 0:
        get_logger().error('7z commands returned non-zero status: %s', proc2.returncode)
        get_logger().debug('stdout: %s', stdout_data)
        get_logger().debug('stderr: %s', stderr_data)
        raise ChildProcessError()

    _process_relative_to(output_dir, relative_to)


def _extract_tar_with_tar(binary, archive_path, output_dir, relative_to):

View on GitHub (pinned to f85e84a480)

Solutions

  1. Delete output_dir (or output_dir/relative_to) before re-extracting
  2. Use a fresh temporary directory for each extraction (tempfile.TemporaryDirectory)
  3. Skip the relative_to argument if you extract into an empty dedicated dir
  4. Handle the FileExistsError and clean up in a retry path

Example fix

// before
extract_tar_file('data.tar.xz', out_dir, relative_to='payload')  # 2nd call fails
// after
import shutil
if (out_dir / 'payload').exists():
    shutil.rmtree(out_dir)
extract_tar_file('data.tar.xz', out_dir, relative_to='payload')
Defensive patterns

Strategy: validation

Validate before calling

import shutil
from pathlib import Path
target = Path(output_dir) / relative_to
if relative_to is not None and target.exists():
    shutil.rmtree(target)

Try / catch

try:
    extract_tar_file(archive, out, relative_to=rel)
except FileExistsError:
    shutil.rmtree(out, ignore_errors=True)
    extract_tar_file(archive, out, relative_to=rel)

Prevention

When it happens

Trigger: Calling extract_tar_file (which dispatches to the 7z extractor) twice with the same output_dir and non-None relative_to without cleaning up, or a previous failed run left output_dir/relative_to behind.

Common situations: Retrying extraction after a crashed run left a stale unpack directory, reusing a cache/temp directory across runs, or two concurrent extractions targeting the same output_dir.

Related errors


AI-assisted analysis of ungoogled-software/ungoogled-chromium@f85e84a480 (2026-08-29). Data as JSON: /api/errors/6345da862d27481a. Report an issue: GitHub.