aio-libs/aiohttp · error · ValueError

' ' does not exist

Error message

'{directory}' does not exist

What it means

StaticResource.__init__ resolves the provided directory with Path(directory).expanduser().resolve(strict=True). The strict=True resolve raises FileNotFoundError if the path does not exist on the filesystem; aiohttp wraps it as ValueError. This fails fast so the server never starts pointing at a missing static root.

Solutions

  1. Verify the directory exists: check the absolute path, fix typos, and ensure it is created before add_static runs.
  2. Use an absolute path constructed from __file__ or a known base (e.g. Path(__file__).parent / 'static').
  3. In Docker/CI, ensure the COPY or build step that creates the directory runs before the server starts.
  4. If the path comes from an env var, validate it at startup and fail with a clear message.

Example fix

// before
app.router.add_static('/static', '/var/www/static')  # missing on this host
// after
import os
app.router.add_static('/static', os.path.abspath('static'))  # relative to CWD, verified to exist
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def resolve_static_dir(directory) -> Path:
    p = Path(directory).expanduser().resolve(strict=True)
    if not p.is_dir():
        raise ValueError(f'{p} is not a directory')
    return p

Try / catch

try:
    app.router.add_static('/static', directory)
except ValueError as e:
    if 'does not exist' in str(e):
        log.error('Static directory missing: %s', directory)
        raise SystemExit(1)
    raise

Prevention

When it happens

Trigger: Calling app.router.add_static('/static', '/nonexistent/path') or web.StaticResource('/static', './missing') where the directory argument does not exist on disk. The check runs at registration/setup time, before the server starts serving.

Common situations: Typo in the directory path; relative path resolved from the wrong working directory (e.g. expected project root but CWD differs); deploying to an environment where the static directory is created later by a different build step; path configured via environment variable that is unset or wrong.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/6294cb0a2f5e6912. Report an issue: GitHub.

Appendix: 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 d041d4d0fd)