HumanSignal/label-studio · error · Http404
Directory indexes are not allowed here.
Error message
Directory indexes are not allowed here.
What it means
The static file serving view (serve in static_serve.py) resolves the requested path under document_root via safe_join; if the resolved fullpath is a directory, it raises Http404 with 'Directory indexes are not allowed here.' Directory listing is deliberately disabled for security.
Source
Thrown at label_studio/core/utils/static_serve.py:61
also set ``show_indexes`` to ``True`` if you'd like to serve a basic index
of the directory. This index view will use the template hardcoded below,
but if you'd like to override it, you can create a template called
``static/directory_index.html``.
If manifest_asset_prefix is provided, we will try to serve the file from the manifest.json
if the file is not found in the document_root.
Example:
path = "main.js"
document_root = "/dist/apps/labelstudio/"
manifest_asset_prefix = "react-app"
manifest_json = {"main.js": "/react-app/main.123456.js"}
fullpath = Path(safe_join(document_root, "main.123456.js"))
"""
path = posixpath.normpath(path).lstrip('/')
fullpath = Path(safe_join(document_root, path))
if fullpath.is_dir():
raise Http404(_('Directory indexes are not allowed here.'))
if manifest_asset_prefix and not fullpath.exists():
possible_asset = get_manifest_asset(path)
manifest_asset_prefix = (
f'/{manifest_asset_prefix}' if not manifest_asset_prefix.startswith('/') else manifest_asset_prefix
)
if possible_asset.startswith(manifest_asset_prefix):
possible_asset = possible_asset[len(manifest_asset_prefix) :]
fullpath = Path(safe_join(document_root, possible_asset))
if not fullpath.exists():
raise Http404(_('“%(path)s” does not exist') % {'path': fullpath})
# Respect the If-Modified-Since header.
statobj = fullpath.stat()
if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), statobj.st_mtime):
return HttpResponseNotModified()
content_type, encoding = static_file_content_type_and_encoding(str(fullpath))
response = RangedFileResponse(request, fullpath.open('rb'), content_type=content_type)
response['Last-Modified'] = http_date(statobj.st_mtime)View on GitHub (pinned to 0b49e9b539)
Solutions
- Request the actual file path, not the directory, e.g. /static/js/app.js.
- Check that asset URLs/href attributes in templates include the filename.
- Verify the reverse proxy/CDN is not stripping the filename from the path.
- Return 404 gracefully in your error handler and link to a valid index asset if you need an entry page.
Example fix
// before <link rel="stylesheet" href="/static/css/"> // after <link rel="stylesheet" href="/static/css/main.css">
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
import posixpath
def is_file_url(static_base, url):
path = posixpath.normpath(urlparse(url).path).rstrip('/')
return path.startswith(static_base) and posixpath.basename(path) != '' Type guard
import posixpath
def points_to_file(path: str) -> bool:
return posixpath.basename(posixpath.normpath(path)) != '' Try / catch
from django.http import Http404
try:
return serve(request, path, document_root)
except Http404 as e:
logging.warning('Static 404: %s (%s)', path, e)
return HttpResponseNotFound('Asset not found') Prevention
- Never link bare directory URLs in templates or docs
- Assert in tests that every referenced static path ends in a filename
- Check reverse-proxy rewrite rules for path stripping
When it happens
Trigger: Requesting a URL that maps to a directory under the static root, e.g. GET /static/js/ or /static/ with no file portion, or a path whose normalization lands on a directory (e.g. /static/js/../js/).
Common situations: Testing the static server by opening a folder URL in a browser; misconfigured base URLs pointing at a directory; broken asset links missing the filename (e.g. /static/css/ instead of /static/css/app.css).
Related errors
- “%(path)s” does not exist
- LABEL_STUDIO_HOST must be a subpath if DOMAIN_FROM_REQUEST i
- SECURE_PROXY_SSL_HEADER must be configured as "<header>,<val
- URL resolves to a reserved network address (block: {subnet})
- Incorrect value type in key "{key}" = "{value}". It should b
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/743f9530708d113f.
Report an issue: GitHub.