windmill-labs/windmill · critical
Server mode requires a database connection
Error message
Server mode requires a database connection
What it means
Windmill's main panics when the binary runs in server mode but no database connection (`conn`) could be established/passed. Server mode fundamentally requires a Postgres connection; proceeding without one is treated as an unrecoverable startup misconfiguration rather than a runtime error.
Source
Thrown at backend/src/main.rs:1155
if !valid_key && !server_mode {
tracing::error!("Invalid license key, workers require a valid license key");
}
if server_mode || mcp_mode {
if let Some(db) = conn.as_sql() {
// only force renewal if invalid but not empty (= expired)
let renewed_now = maybe_renew_license_key_on_start(
&HTTP_CLIENT,
&db,
!valid_key && !LICENSE_KEY_ID.load().is_empty(),
)
.await;
if renewed_now {
if let Err(err) = reload_license_key(&conn).await {
tracing::error!("Failed to reload license key: {err:#}");
}
}
} else {
panic!("Server mode requires a database connection");
}
}
}
if server_mode || worker_mode || indexer_mode || mcp_mode {
let port_var = std::env::var("PORT")
.or_else(|_| std::env::var("BACKEND_PORT"))
.ok()
.and_then(|x| x.parse().ok());
let port = if server_mode || indexer_mode || mcp_mode {
port_var.unwrap_or(DEFAULT_PORT as u16)
} else {
port_var.unwrap_or(0)
};
let default_base_internal_url = format!("http://localhost:{}", port.to_string());
// since it's only on server mode, the port is statically definedView on GitHub (pinned to e474e8803c)
Solutions
- Set a correct DATABASE_URL env var (e.g. postgres://user:pass@host:5432/windmill)
- Verify Postgres is running and reachable from the binary (psql to the same URL)
- If you intentionally want no DB, run a non-server mode (worker with queue access via separate config, or agent mode in EE)
- Check startup logs just above the panic for the underlying connection error (auth, DNS, TLS)
Example fix
// before MODE=server # no DATABASE_URL // after export DATABASE_URL=postgres://postgres:changeme@localhost:5432/windmill ./windmill server
Defensive patterns
Strategy: validation
Validate before calling
// shell check before starting the server
if [ "$MODE" != "agent" ] && [ -z "$DATABASE_URL" ]; then
echo "FATAL: server/worker mode requires DATABASE_URL" >&2; exit 1
fi
# plus a reachability check:
psql "$DATABASE_URL" -c 'select 1' || { echo 'DB unreachable'; exit 1; } Prevention
- Validate DATABASE_URL in your entrypoint/startup script before exec'ing the binary
- Run health checks on Postgres in orchestrator readiness probes
- Keep DB credentials in secret management, injected consistently into containers
- Read startup logs above the panic — the real connection error (auth/DNS/TLS) is printed there
When it happens
Trigger: Starting the windmill binary with MODE=server (default) while `DATABASE_URL` is missing/unreachable, or the connection setup failed so `conn` is None at the check in windmill_main.
Common situations: Forgot to set DATABASE_URL; Postgres not running or wrong host/port/credentials; DB env var typo; running the binary in a container without the DB service linked.
Related errors
- BASE_INTERNAL_URL is required in agent mode
- Agent mode is only available in the EE, ignoring...
- WINDMILL_DIR must not be empty
- ${what} failed:\n${output}
- No instance found, please add one first
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/8f9172e44e5f75b7.
Report an issue: GitHub.