Initializing Enclave...

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: psql cannot find a database named mydb on 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 \l in psql, create it if missing via createdb mydb, and audit your PGDATABASE/PGHOST environment 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:

  1. App pods crash-loop — connection pool (PgBouncer, pgpool-II) exhausts retry budget, returns 500s to all upstream services.
  2. 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.
  3. Data written to the wrong database — if PGDATABASE is unset, psql defaults 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.
  4. In containerized environments (Docker/K8s): POSTGRES_DB in the init container and PGDATABASE in 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)

Related Diagnostics

"Part of the Syntax Utility Matrix."

View all 153 Syntax Tools →