ungoogled-software/ungoogled-chromium · error · FileNotFoundError

Could not find relative_to directory in extracted files: %s

Error message

Could not find relative_to directory in extracted files: %s

What it means

Raised by _process_relative_to when a relative_to path is supplied but the corresponding directory does not exist inside the unpacked output after extraction. The library uses relative_to to hoist a nested directory (e.g. 'payload/bin') to the top level of output_dir; if the archive did not produce that directory, extraction is considered wrong and it aborts.

Source

Thrown at utils/_extraction.py:83

    if Path(extractor_cmd).is_file():
        return extractor_cmd
    return shutil.which(extractor_cmd)


def _process_relative_to(unpack_root, relative_to):
    """
    For an extractor that doesn't support an automatic transform, move the extracted
    contents from the relative_to/ directory to the unpack_root

    If relative_to is None, nothing is done.
    """
    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

View on GitHub (pinned to f85e84a480)

Solutions

  1. List the archive contents (tar -tf / 7z l) and set relative_to to the exact inner directory path it contains
  2. Verify extraction succeeded (returncode 0, files present in output_dir) before blaming relative_to
  3. Ensure relative_to uses os-style forward slashes relative to the archive root
  4. Pass relative_to=None if you do not need the nested directory hoisted

Example fix

// before
extract_tar_file('chrome.tar.xz', out, relative_to='chrome-linux')
// after (after inspecting: archive root is chrome-linux64)
extract_tar_file('chrome.tar.xz', out, relative_to='chrome-linux64')
Defensive patterns

Strategy: validation

Validate before calling

import tarfile
names = set().union(*[set(m.names) for m in [tarfile.open(archive)]]) if False else None
# simpler: list archive dirs
import subprocess
listing = subprocess.run(['tar', '-tf', str(archive_path)], capture_output=True, text=True).stdout
inner = {n.split('/')[0] for n in listing.splitlines() if n.strip()}
assert relative_to in inner or any(n.startswith(relative_to + '/') for n in listing.splitlines()), f'{relative_to} not in archive'

Type guard

def has_relative_dir(unpack_root, relative_to):
    from pathlib import Path
    return relative_to is None or (Path(unpack_root) / relative_to).is_dir()

Try / catch

try:
    extract_tar_file(archive, out, relative_to='chrome-linux')
except FileNotFoundError:
    logger.warning('relative_to missing in archive; inspecting layout')
    # re-extract with corrected relative_to or None

Prevention

When it happens

Trigger: Calling extract_tar_file / extract_with_7z / extract_with_winrar with a relative_to value naming a directory that is absent from the archive, misspelled, uses the wrong separator, or extraction failed silently leaving no such folder.

Common situations: Archives that changed layout between versions (inner folder renamed like 'chrome-linux' -> 'chrome-linux64'), typo in the relative_to string, passing a Windows-style path with backslashes, or the archive extracting as a single root directory the caller did not account for.

Related errors


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