How to Fix PostgreSQL FATAL: database 'mydb' does not exist (psql Connection Error)
Threat/Impact Level: HIGH | Exploitability/Downtime Risk: HIGH | Time to Fix: 5 mins
TL;DR
- What broke:
psqlcannot find a database namedmydbon the target PostgreSQL cluster — it either was never created, the name is wrong, or you're hitting the wrong host/port. - How to fix it: Verify the database exists with
\lin psql, create it if missing viacreatedb mydb, and audit yourPGDATABASE/PGHOSTenvironment variables. - Fast path: Use our Client-Side Sandbox below to auto-refactor this — paste your connection string and let it diagnose the mismatch without sending your credentials anywhere.
The Incident (What does the error mean?)
Raw error output:
$ psql -d mydb
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed:
FATAL: database "mydb" does not exist
PostgreSQL's pg_hba.conf authentication passed — your credentials are fine. The cluster is up. The problem is the catalog lookup: PostgreSQL queries pg_database for a row where datname = 'mydb' and finds nothing. Connection is immediately terminated. Every application, migration runner, and health check depending on this connection string is now dead.
The Attack Vector / Blast Radius
This is not just a typo. The cascading failure path in production:
- App pods crash-loop — connection pool (PgBouncer, pgpool-II) exhausts retry budget, returns 500s to all upstream services.
- Migration runners fail silently — tools like Flyway or Alembic may exit 0 with a misleading log if misconfigured, leaving your schema in an unknown state.
- Data written to the wrong database — if
PGDATABASEis unset,psqldefaults to the OS username as the database name. On a shared cluster, that database may actually exist under a different owner, causing writes to land in an unintended location with no immediate error. - In containerized environments (Docker/K8s):
POSTGRES_DBin the init container andPGDATABASEin the app container can drift independently across Helm chart upgrades, creating a split-brain config that's invisible until the first rollout.
The silent danger: PGDATABASE environment variable overrides -d flag in some client versions. Always confirm which value is actually being used.
How to Fix It (The Solution)
Step 1 — Confirm what databases actually exist
# Connect to the default maintenance database
psql -U postgres -d postgres -c "\l"
# or
psql -U postgres -d postgres -c "SELECT datname FROM pg_database WHERE datistemplate = false;"
Step 2 — Basic Fix: Create the missing database
- psql -d mydb
+ createdb -U postgres mydb
+ psql -U postgres -d mydb
Step 3 — Enterprise Best Practice: Declarative database provisioning
Never create databases manually in production. Use idempotent provisioning.
Terraform (recommended for cloud-managed PG / RDS / Cloud SQL):
- # Database created manually via psql — no IaC record, no drift detection
+ resource "postgresql_database" "mydb" {
+ name = "mydb"
+ owner = postgresql_role.app_user.name
+ template = "template0"
+ encoding = "UTF8"
+ lc_collate = "en_US.UTF-8"
+ lc_ctype = "en_US.UTF-8"
+ connection_limit = 100
+ allow_connections = true
+ }
Fix environment variable drift in Docker Compose:
services:
app:
environment:
- DATABASE_URL: postgres://user:pass@db:5432/wrongdb
+ DATABASE_URL: postgres://user:pass@db:5432/mydb
db:
image: postgres:16
environment:
- POSTGRES_DB: appdb
+ POSTGRES_DB: mydb
Fix in Kubernetes Secret/ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
- PGDATABASE: "wrongdb"
+ PGDATABASE: "mydb"
Step 4 — Audit environment variable precedence
# What is psql actually using?
psql -U postgres -c "SELECT current_database();"
# Check all PG* env vars in scope
env | grep ^PG
# In a running K8s pod
kubectl exec -it <pod> -- env | grep PG
💡 Tired of pasting proprietary configs into ChatGPT? Generic AI tools log your company's ARNs, DB strings, and private keys. StackEngine is a zero-backend, pure Client-Side WASM utility. Drop your failing config into the sandbox above. We redact your secrets locally in the browser and auto-generate the refactored code using your own API key.
Prevention in CI/CD
1. Pre-flight database existence check in your pipeline
#!/bin/bash
# ci/check-db.sh — fail fast before migrations run
DB_EXISTS=$(psql -U "$PGUSER" -d postgres -tAc \
"SELECT 1 FROM pg_database WHERE datname='${PGDATABASE}'")
if [[ "$DB_EXISTS" != "1" ]]; then
echo "FATAL: Database '${PGDATABASE}' does not exist on ${PGHOST}. Aborting."
exit 1
fi
2. Checkov / tfsec — catch IaC drift
# Scan Terraform for missing postgresql_database resources
checkov -d ./terraform --check CKV_PG_*
3. OPA/Conftest policy — enforce DB name consistency
# policy/pg_database_name.rego
package main
deny[msg] {
input.kind == "ConfigMap"
db := input.data.PGDATABASE
not db == "mydb"
msg := sprintf("PGDATABASE must be 'mydb', got '%v'", [db])
}
4. Helm chart lint gate
# .github/workflows/lint.yml
- name: Helm lint with strict values
run: |
helm lint ./charts/app \
--set postgresql.database=mydb \
--strict
5. Integration test smoke check (GitHub Actions)
- name: Verify DB exists post-deploy
run: |
psql "$DATABASE_URL" -c "SELECT current_database();" || \
(echo '::error::Database connection failed' && exit 1)