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
- Verify the directory exists: check the absolute path, fix typos, and ensure it is created before add_static runs.
- Use an absolute path constructed from __file__ or a known base (e.g. Path(__file__).parent / 'static').
- In Docker/CI, ensure the COPY or build step that creates the directory runs before the server starts.
- 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
- Use absolute paths derived from __file__ for static roots.
- Add a startup check that the directory exists and is readable.
- In containers, ensure the COPY step runs before the server starts.
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
- ' ' is not a directory
- OPTIONS route was set already
- 403: Forbidden
- 404: Not Found
- aiohttp only supports http(s) proxies
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)