aio-libs/aiohttp · error · ValueError

'{directory}' does not exist

Error message

'{directory}' does not exist

What it means

Raised as ValueError by StaticResource.__init__ when Path(directory).resolve(strict=True) raises FileNotFoundError — i.e. the configured static directory does not exist on disk. The static resource needs a real directory to serve files from at setup time, so a missing path is rejected immediately rather than 404-ing every request.

Source

Thrown at aiohttp/web_urldispatcher.py:519

    VERSION_KEY = "v"

    def __init__(
        self,
        prefix: str,
        directory: PathLike,
        *,
        name: str | None = None,
        expect_handler: _ExpectHandler | None = None,
        chunk_size: int = DEFAULT_CHUNK_SIZE,
        show_index: bool = False,
        break_symlink_sandbox: bool = False,
        append_version: bool = False,
    ) -> None:
        super().__init__(prefix, name=name)
        try:
            directory = Path(directory).expanduser().resolve(strict=True)
        except FileNotFoundError as error:
            raise ValueError(f"'{directory}' does not exist") from error
        if not directory.is_dir():
            raise ValueError(f"'{directory}' is not a directory")
        self._directory = directory
        self._show_index = show_index
        self._chunk_size = chunk_size
        self._break_symlink_sandbox = break_symlink_sandbox
        self._expect_handler = expect_handler
        self._append_version = append_version

        self._routes = {
            "GET": ResourceRoute(
                "GET", self._handle, self, expect_handler=expect_handler
            ),
            "HEAD": ResourceRoute(
                "HEAD", self._handle, self, expect_handler=expect_handler
            ),
        }
        self._allowed_methods = set(self._routes)

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Verify the directory exists: check with Path(directory).resolve() before add_static.
  2. Use an absolute path derived from __file__: Path(__file__).parent / 'static'.
  3. Ensure build/copy steps (npm run build, COPY in Dockerfile) run before server startup.
  4. In containers, confirm the directory is present at the expected absolute path.

Example fix

# before
app.router.add_static('/static', '/var/www/assets')  # missing

# after
from pathlib import Path
static_dir = Path(__file__).parent / 'assets'
app.router.add_static('/static', static_dir)
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def resolve_static_dir(directory):
    p = Path(directory).expanduser()
    if not p.exists():
        raise FileNotFoundError(f"static directory does not exist: {p}")
    return p.resolve()

Type guard

from pathlib import Path

def directory_exists(directory) -> bool:
    return Path(directory).expanduser().exists()

Try / catch

try:
    app.router.add_static('/static', directory)
except ValueError as e:
    if 'does not exist' in str(e):
        raise SystemExit(f"Static dir missing: {e}") from e
    raise

Prevention

When it happens

Trigger: Calling app.router.add_static('/static', '/wrong/path') or web.static('/s', './missing') where the directory does not exist. Relative paths resolved against an unexpected working directory also trigger it.

Common situations: Deploying with a different working directory than dev; build step that creates the assets dir not yet run; typo in the path; containerized app where the static dir isn't copied into the image; path from config pointing to a host path not mounted.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/6294cb0a2f5e6912.json. Report an issue: GitHub.