oraios/serena · error · FileNotFoundError

Archive not found: {self.archive_path}

Error message

Archive not found: {self.archive_path}

What it means

Raised by ZipArchive.extract_all() when the archive path given to the extractor does not exist on disk. It is a plain FileNotFoundError wrapped with a clearer message naming the missing archive path, thrown before any zip reading starts.

Source

Thrown at src/solidlsp/util/zip.py:51

        :param archive_path: Path to the ZIP archive file
        :param extract_dir: Directory where files will be extracted
        :param verbose: Whether to log status messages
        :param include_patterns: List of glob patterns for files to extract (None = all files)
        :param exclude_patterns: List of glob patterns for files to skip
        """
        self.archive_path = Path(archive_path)
        self.extract_dir = Path(extract_dir)
        self.verbose = verbose
        self.include_patterns = include_patterns or []
        self.exclude_patterns = exclude_patterns or []

    def extract_all(self) -> None:
        """
        Extract all files from the archive, skipping any that fail.
        """
        if not self.archive_path.exists():
            raise FileNotFoundError(f"Archive not found: {self.archive_path}")

        if self.verbose:
            log.info(f"Extracting from: {self.archive_path} to {self.extract_dir}")

        with zipfile.ZipFile(self.archive_path, "r") as zip_ref:
            for member in zip_ref.infolist():
                if self._should_extract(member.filename):
                    self._extract_member(zip_ref, member)
                elif self.verbose:
                    log.info(f"Skipped: {member.filename}")

    def _should_extract(self, filename: str) -> bool:
        """
        Determine whether a file should be extracted based on include/exclude patterns.

        :param filename: The file name from the archive
        :return: True if the file should be extracted
        """

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Check the archive_path in the error message exists (ls / os.path.exists) and fix the path passed to the ZipArchive constructor
  2. Run or re-create the step that produces the archive (download/build/fixture setup) before calling extract_all()
  3. In tests, ensure fixtures are created in setUp/tempdir with the same path handed to ZipArchive, and verify with assertTrue(archive_path.exists()) before extracting
  4. Add an existence check or explicit error handling around extract_all() if the archive may legitimately be absent
  5. Watch for tests running in parallel sharing a temp directory and deleting each other's archives; isolate per-test temp dirs

Example fix

// before
archive = ZipArchive(zip_path, extract_dir)
archive.extract_all()  # FileNotFoundError: Archive not found: ...

// after
if not zip_path.exists():
    zip_path = build_fixture_zip(zip_path)  # create the archive first
archive = ZipArchive(zip_path, extract_dir)
archive.extract_all()
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def ensure_archive_ready(zip_path: Path) -> bool:
    return zip_path.is_file() and zip_path.stat().st_size > 0

if not ensure_archive_ready(zip_path):
    raise RuntimeError(f"Archive missing or empty before extraction: {zip_path}")

Type guard

def is_existing_zip(path: Path) -> bool:
    return path.is_file() and path.suffix == ".zip" and path.stat().st_size > 0

Try / catch

try:
    archive.extract_all()
except FileNotFoundError as e:
    logging.error("Archive unavailable: %s", e)
    create_or_download_archive(archive.archive_path)
    archive.extract_all()

Prevention

When it happens

Trigger: Calling extract_all() (directly or via test helpers for include/exclude patterns) when self.archive_path does not exist — i.e. the ZipFile path was constructed with a path to a file that was never created, was deleted, or the path string is wrong.

Common situations: Tests that build fixture archives in setUp but write them to a different directory than the ZipArchive was pointed at; a download/prepare step that silently failed so the .zip never materialized; typos or relative-vs-absolute path confusion; the archive deleted by a cleanup step or another test before extract_all runs.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/951519ef2450012b. Report an issue: GitHub.