aio-libs/aiohttp · error · ValueError
'{directory}' is not a directory
Error message
'{directory}' is not a directory What it means
Raised as ValueError by StaticResource.__init__ when the resolved path exists but is not a directory (e.g. it points to a regular file). StaticResource can only serve from a directory, so passing a file path is rejected after the existence check passes.
Source
Thrown at aiohttp/web_urldispatcher.py:521
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)
def url_for( # type: ignore[override]View on GitHub (pinned to c0ef574e29)
Solutions
- Pass the containing directory: app.router.add_static('/static', Path(file).parent).
- To serve a single file, register a route that returns web.FileResponse(path) instead.
- Double-check the path with Path(p).is_dir() before add_static.
Example fix
# before
app.router.add_static('/static', '/srv/app/index.html')
# after
app.router.add_static('/static', '/srv/app') Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def ensure_is_dir(directory):
p = Path(directory).expanduser().resolve()
if not p.is_dir():
raise ValueError(f"not a directory: {p}")
return p Type guard
from pathlib import Path
def is_directory_path(directory) -> bool:
return Path(directory).expanduser().resolve().is_dir() Try / catch
try:
app.router.add_static('/static', directory)
except ValueError as e:
if 'not a directory' in str(e):
directory = Path(directory).parent # fall back to parent dir
app.router.add_static('/static', directory) Prevention
- Pass directories, not files, to add_static.
- Use FileResponse in a route to serve a single file.
- Validate Path(p).is_dir() in config loaders.
When it happens
Trigger: Calling app.router.add_static('/static', '/path/to/index.html') — pointing at a file rather than its containing directory. Also pointing at a device node or socket.
Common situations: Confusing the directory path with a file path; copy-paste of a file path from config; intending to serve a single file but using add_static instead of a route returning FileResponse.
Related errors
- '{directory}' does not exist
- Domain cannot be empty
- Scheme not supported
- {method} is not allowed HTTP method
- Invalid path '{path}'['{part}']
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/f29dad22d642c240.json.
Report an issue: GitHub.