Fix PostgreSQL FATAL: database does not exist
Learn why PostgreSQL reports FATAL: database does not exist, how to identify the requested database name, and when to create, restore, or correct it.
The PostgreSQL error FATAL: database "app" does not exist means the server accepted the connection attempt far enough to know which database name the client requested, but it could not find a database with that name in the cluster. It is different from a bad password, a missing role, or a network problem. The client reached PostgreSQL; the database target is wrong or absent.
This often appears during the first production deploy, after a restore into a new managed environment, in CI migrations, or when a local command relies on defaults. The fastest fix is to prove which database name the client is sending before creating anything new.
Why PostgreSQL asks for the wrong database
PostgreSQL connections include host, port, user, database name, and optional parameters such as SSL mode. The database name can come from a URI path, a keyword-style connection string, the -d option in psql, PGDATABASE, or driver configuration. If omitted, libpq tools commonly default the database name to the user name.
That default explains many surprises. A developer may run psql -U app_user expecting the production application database, but the client may ask for a database also named app_user. A copied URL may contain the right host and password but the wrong path after the slash.
The error is also common after provisioning because cluster names, project names, user names, and database names are easy to mix up. Treat those as separate values.
Confirm the requested database name
Start by printing the exact connection settings used by the failing process, with passwords redacted. For a PostgreSQL URI, the database name is the path segment after the host and port:
postgresql://app_user:***@db.example.com:5432/appdb?sslmode=require
^^^^^
For psql, make the database explicit so environment defaults do not hide the issue:
psql "host=db.example.com port=5432 user=app_user dbname=appdb sslmode=require"
# or
psql -h db.example.com -p 5432 -U app_user -d appdb
If you can connect to an administrative or default database on the same cluster, list databases and compare the spelling. Unquoted names are folded to lower case. A database created with quoted mixed-case spelling must be referenced exactly, which is usually not worth the friction.
select datname
from pg_database
where datistemplate = false
order by datname;
Choose the right fix
Do not automatically create the missing database named in the error. Sometimes the name is the intended production database. Sometimes it is a symptom of a missing dbname, a typo, or a secret from the wrong environment.
| Symptom | Likely cause | Safer fix |
|---|---|---|
| Error asks for a database with the same name as the user | Client omitted dbname and used the user name as a default | Set the intended database name explicitly in the connection string |
App fails but local psql works | Runtime and local commands use different environment variables | Compare deployed secrets with the working connection values |
Migration job points to postgres or defaultdb | The job used a cluster default instead of the app database | Update the migration database URL before running schema changes |
| Database is absent after restore | Roles or data were restored but the target database was not created | Create the intended database, then restore into it deliberately |
| Mixed-case or hyphenated name fails inconsistently | Quoting or URI parsing is inconsistent | Prefer a simple lowercase database name for application use |
The safest first repair is usually configuration: set the database name explicitly in the application, worker, migration, and console connection strings. Create a database only when you have confirmed that the intended database is genuinely absent.
Creating the database deliberately
When the database really does not exist, create it from a role with database creation privileges or through your managed provider dashboard. PostgreSQL documents CREATE DATABASE as a command that copies from a template database, and it cannot run inside an ordinary transaction block. That matters for migration tools that wrap every statement in a transaction.
create database appdb owner app_owner;
After creation, connect to the new database before applying schema migrations. Grants on the cluster do not automatically mean the application role can use every schema and table. A common production pattern is to keep the database owner, migration role, and runtime role separate.
If the missing database should contain existing production data, do not create an empty database and point the app at it just to clear the error. Restore the correct backup, verify row counts, and run migrations only after you know the data is present. ArmorDB users can use the backup documentation as the operational checklist.
Validate the final connection path
Once the database name is corrected or created, test the same path that failed. If production failed, redeploy the secret and run the production health check. If CI migrations failed, rerun the CI job with the same environment variables.
A useful smoke test is intentionally boring: connect, ask PostgreSQL which database and user were selected, and run a harmless schema query.
select current_database(), current_user;
select schema_name from information_schema.schemata order by schema_name limit 5;
For pooled setups, remember that PgBouncer can add another layer of configuration. The client may connect to the pooler database name, and the pooler may map that name to a server-side database. If the direct PostgreSQL connection works but the pooled path fails, check the pooler mapping rather than changing the application schema.
Common mistakes
The biggest mistake is creating a database with the accidental name from the error. If a serverless function asked for node or app_user because dbname was omitted, creating that database leaves the real configuration bug in place. Another mistake is confusing this with FATAL: role does not exist; database names and role names are separate objects even when teams choose similar names.
A third mistake is fixing only the web process. Background workers, migration commands, preview deployments, and one-off scripts often carry their own database URLs. Search all deployment secrets and CI variables before declaring the incident closed.
Takeaway
FATAL: database does not exist is a target-selection problem. Identify the database name the client actually sends, compare it with pg_database, and then either correct the connection string or create and restore the intended database. In managed PostgreSQL, keeping database name, role name, and project name visibly separate prevents this small configuration error from turning into a confusing deploy failure.
Sources and further reading
Topic
Short-Form & Quick Fixes
Updated
Jul 17, 2026
Read time
5 min read
ArmorDB Engineering writes about PostgreSQL operations, security, and infrastructure decisions for teams building production apps on ArmorDB.
Read next
Tech-News & Trends · 6 min read
PostgreSQL 18 ANALYZE VERBOSE: Better Maintenance Observability
PostgreSQL 18 adds WAL, CPU, and read detail to ANALYZE VERBOSE, giving production teams a clearer view of table statistics maintenance.
Read articleData-Specs / Vergleiche · 8 min read
PostgreSQL Storage Autoscaling vs Fixed Capacity
A practical comparison of PostgreSQL storage autoscaling, fixed capacity, monitoring signals, and upgrade decisions for managed database teams.
Read article