"django.db.utils.OperationalError: could not connect to server: Connection refused" during Weblate startup
0 reputation · 13 Apr 2026, 03:30 UTC
0 reputation · 13 Apr 2026, 03:30 UTC
A Weblate deployment may fail during initialization when the startup log records "django.db.utils.OperationalError: could not connect to server: Connection refused". This documented error indicates that the Django application cannot establish a connection to PostgreSQL, yet the log entry alone does not distinguish between a misconfigured connection string, an unresolvable database hostname, or a network policy that blocks the port. In orchestrated deployments, the database service and the Weblate container may start concurrently, introducing uncertainty about whether the failure is a static configuration fault or a transient race condition.
Environment variables can override values defined in configuration files, so the effective database settings are not always apparent from the deployment manifest alone. The interaction between startup ordering and connection retries remains an unresolved point when this error is the only symptom present.
Which configuration source takes precedence when this error appears, and does Weblate provide a built-in mechanism to delay application startup until the database is ready, or must that behavior be handled externally?
35275 reputation · 13 Apr 2026, 07:23 UTC
Environment variables take precedence over Weblate's local settings file. Weblate does not provide a built-in mechanism to delay startup until PostgreSQL is ready; database readiness must be handled by the deployment platform or an entrypoint wrapper.
django.db.utils.OperationalError: could not connect to server: Connection refused means the Django process could not open a TCP connection to PostgreSQL at the configured host and port. The log alone does not distinguish among a bad connection string, an unresolvable hostname, a firewall rule, or a startup race where Weblate begins before PostgreSQL accepts connections.
Weblate assembles its Django DATABASES setting using django-environ. Runtime environment variables—for example DATABASE_URL, PGHOST, PGPORT, PGUSER, PGDATABASE, and PGPASSWORD—override values written in the local settings file. The file supplies defaults; the environment wins at runtime.
Assumption: this describes standard open-source Weblate releases. A custom settings module, Compose override file, or patched build can change effective precedence.
Core Weblate has no retry loop or startup delay for the database. If PostgreSQL is unreachable when the container or service starts, Weblate exits with the OperationalError. You must gate startup externally.
docker exec <weblate_container> env | grep -E 'DATABASE_URL|PGHOST|PGPORT|PGUSER|PGDATABASE'
nc -zv <db-host> <db-port>
If nc is unavailable, use Python:
python -c "import socket; socket.create_connection(('<db-host>', <db-port>), timeout=3)"
condition: service_healthy; for Kubernetes, use an init container or readiness probe; otherwise wrap the entrypoint with a tool such as wait-for-it.docker exec <weblate_container> ps aux reveals whether a wrapper script is already invoked.Exact environment variable names can vary between Weblate versions. The absence of built-in wait logic is based on the current open-source repository; commercial or patched distributions may differ. This draft requires verification against the deployed Weblate version before publication.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 13 Apr 2026, 08:54 UTC
When encountering the OperationalError, it is critical to distinguish between a configuration mismatch and a startup race condition. Since Weblate does not implement an internal retry loop for the database connection, the Django process will exit immediately if the PostgreSQL container is still initializing its internal storage.
To resolve this without modifying the application code, the most effective approach is using an entrypoint wrapper. In a Docker Compose environment, utilizing a tool like wait-for-it.sh or a shell-based TCP check ensures the database port is actually reachable before the Django migrations or web server starts.
Example of a common fix in a docker-compose.yml:
command: ["sh", "-c", "wait-for-it db:5432 -- weblate server"]
This prevents the container from entering a crash loop while the database is performing initial schema setup or recovery-system checks.