ungoogled-software/ungoogled-chromium · error · FileExistsError

destination already exists: {destination}

Error message

destination already exists: {destination}

What it means

merge_patches raises FileExistsError when the destination directory already exists and prepend is not set. The function only merges into a fresh (nonexistent) destination, or an existing one when explicitly prepending, to avoid silently overwriting an existing patch set.

Source

Thrown at utils/patches.py:173


def merge_patches(source_iter, destination, prepend=False):
    """
    Merges GNU quilt-formatted patches directories from sources into destination

    destination must not already exist, unless prepend is True. If prepend is True, then
    the source patches will be prepended to the destination.
    """
    series = []
    known_paths = set()
    if destination.exists():
        if prepend:
            if not (destination / 'series').exists():
                raise FileNotFoundError(
                    f"Could not find series file in existing destination: {destination / 'series'}")
            known_paths.update(generate_patches_from_series(destination))
        else:
            raise FileExistsError(f'destination already exists: {destination}')
    for source_dir in source_iter:
        patch_paths = tuple(generate_patches_from_series(source_dir))
        patch_intersection = known_paths.intersection(patch_paths)
        if patch_intersection:
            raise FileExistsError(f'Patches from {source_dir} have conflicting paths '
                                  f'with other sources: {patch_intersection}')
        series.extend(patch_paths)
        _copy_files(patch_paths, source_dir, destination)
    if prepend and (destination / 'series').exists():
        series.extend(generate_patches_from_series(destination))
    with (destination / 'series').open('w') as series_file:
        series_file.write('\n'.join(map(str, series)))


def _apply_callback(args, parser_error):
    logger = get_logger()
    patch_bin_path = None
    if args.patch_bin is not None:

View on GitHub (pinned to f85e84a480)

Solutions

  1. Delete or move the existing destination directory before merging
  2. Pass prepend=True if you intend to merge into the existing destination
  3. Point destination at a new, unique path for this merge
  4. Make the merge idempotent: check destination.exists() and skip or clean up before calling

Example fix

# before
merge_patches(sources, dest)  # FileExistsError on rerun
# after
import shutil
if dest.exists():
    shutil.rmtree(dest)
merge_patches(sources, dest)
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
dest = Path(destination)
assert not dest.exists() or prepend, f'destination exists: {dest}; pass prepend=True or remove it'

Type guard

def destination_is_fresh(dest):
    return not Path(dest).exists()

Try / catch

try:
    merge_patches(sources, dest)
except FileExistsError as e:
    logger.warning('stale destination, recreating: %s', e)
    shutil.rmtree(dest)
    merge_patches(sources, dest)

Prevention

When it happens

Trigger: Calling merge_patches / merge_platform_patches with a `destination` path that already exists as a directory while prepend=False (default). Also occurs on repeated invocations of the same merge (e.g. _merge_callback reruns) without cleanup.

Common situations: Re-running a merge script after a previous successful run; destination collides with an existing platform patches directory; wrong destination constant; a build tool retrying the merge step.

Related errors


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