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 defined

View on GitHub (pinned to e474e8803c)

Solutions

  1. Set a correct DATABASE_URL env var (e.g. postgres://user:pass@host:5432/windmill)
  2. Verify Postgres is running and reachable from the binary (psql to the same URL)
  3. If you intentionally want no DB, run a non-server mode (worker with queue access via separate config, or agent mode in EE)
  4. 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

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


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/8f9172e44e5f75b7. Report an issue: GitHub.