-
Notifications
You must be signed in to change notification settings - Fork 107
Description
Describe the bug
I ran into an issue where Limiter tries to read a .env file even when I'm already passing environment variables through Docker. My container doesn't mount .env (and shouldn't need to - I'm using docker run --env-file like the Docker docs recommend), but slowapi still attempts to load it through starlette's Config class.
The problem is that starlette's Config defaults to loading .env when you don't explicitly tell it not to. In production containers where environment variables come from the orchestration layer (Docker, Kubernetes, etc.) and there's no .env file to read, this causes warnings and can even lead to startup failures depending on file permissions
To Reproduce
Minimal example:
from slowapi import Limiter
from slowapi.util import get_remote_address
import os
# Environment variables already set (e.g., via docker run --env-file)
os.environ['RATE_LIMIT_STORAGE'] = 'memory://'
# This tries to read .env file, causing permission errors if file doesn't exist
# or has wrong permissions in Docker
limiter = Limiter(
key_func=get_remote_address,
storage_uri=os.getenv("RATE_LIMIT_STORAGE"),
default_limits=["1000 per hour"]
)Docker context:
# Dockerfile - typical production setup
FROM python:3.13-slim
WORKDIR /app
COPY . .
RUN pip install slowapi fastapi
CMD ["python", "app.py"]# Run with environment variables via --env-file (best practice)
docker run --env-file config.env myapp
# Error: starlette.config tries to open('.env') which doesn't exist
# UserWarning: Config file '.env' not found.Error message:
/usr/local/lib/python3.13/site-packages/starlette/config.py:61: UserWarning: Config file '.env' not found.
warnings.warn(f"Config file '{env_file}' not found.")
Expected behavior
I'd expect that when my environment variables are already set (via --env-file, Kubernetes ConfigMaps, etc.), slowapi wouldn't try to read any files. Just read from os.environ and call it a day - no file I/O needed at initialization.
Current Workaround
I got it working by setting config_filename="/dev/null":
limiter = Limiter(
key_func=get_remote_address,
storage_uri=os.getenv("RATE_LIMIT_STORAGE"),
default_limits=["1000 per hour"],
config_filename="/dev/null" # Prevent auto-loading .env
)It works, but it's not obvious that you need to do this, and I only found it by digging through the source code.
Your app
- Framework: FastAPI 0.115.6
- slowapi version: 0.1.9 (latest)
- Python version: 3.13
- Environment: Docker container (production)
Additional context
Looking at the code, Limiter.__init__ calls Config(env_file=config_filename) where config_filename defaults to ".env", which triggers starlette to try loading the file.
I noticed PR #170 documents the config_filename parameter, but doesn't change the default behavior. This hits anyone running containers the recommended way (environment variables via orchestration, no .env file mounted).
Some possible fixes:
- Default
config_filenametoNoneand document that users who want.envloading should explicitly set it - Only try loading
.envif it exists and is readable - Follow starlette 1.0+ where
env_fileis opt-in rather than default
This affects any production deployment following 12-factor app config principles - environment variables should just work without needing workarounds or file mounts.