FATAL: database "appdb" does not exist means the login worked but the database you asked for was never created on that server. Create it with CREATE DATABASE appdb while connected to a database that does exist, such as postgres, then connect again.

If the name in the error is your user name rather than a database you typed, you gave no database at all: psql and libpq then use the user name as the database name. Add -d postgres or the real database name.

The error

docker exec fix4-pg18 psql -U postgres -d appdb
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  database "appdb" does not exist

The SQLSTATE is not in psql's message; the server log, with log_error_verbosity = verbose, shows it:

FATAL:  3D000: database "appdb" does not exist
LOCATION:  InitPostgres, postinit.c:1014

Why it happens

A PostgreSQL connection always targets one database, and the server checks that it exists right after it accepts the role. Code 3D000 is "invalid catalog name": authentication succeeded, so the user name and the password are fine. The missing piece is the database itself.

Two things usually lead here. The postgres Docker image creates one database on first start, named by POSTGRES_DB, and that variable defaults to the user name, so a container started with only POSTGRES_PASSWORD has postgres and the templates and nothing else; a connection string that says Database=appdb fails until someone creates it. The second is the default: when no database is given, psql uses the user name. Straight after creating a role called app, a bare psql -U app failed on this server with FATAL: database "app" does not exist, the same error with a name nobody typed.

The fix

docker exec fix4-pg18 psql -U postgres -c "CREATE DATABASE appdb"
CREATE DATABASE

docker exec fix4-pg18 psql -U postgres -d appdb -c "SELECT current_database()"
 current_database
------------------
 appdb
(1 row)

The first command runs without -d, so it connects to the postgres database (the user name again), which exists, and creates appdb from there. fix4-pg18 is the test's container name; use yours. If an application role will own the tables, give it the database at creation time: CREATE DATABASE appdb2 OWNER app was run on the same server and app could create a table in it straight away. On a brand-new container you can instead set POSTGRES_DB=appdb, but only when the data volume is empty; the image ignores it once the data directory exists.

How it was reproduced

A fresh postgres:18 container (PostgreSQL 18.4, Debian build) on Docker Desktop 4.91.0 under Windows 11, started with only POSTGRES_PASSWORD. Running psql -U postgres -d appdb inside it produced the error; the SQLSTATE line came from the server log of the same attempt after raising log_error_verbosity. The CREATE DATABASE and the second connection were run straight after, with the output shown.

Frequently asked

Why does psql say database does not exist when I only gave a user name?
When no database is given, psql and libpq use the user name as the database name. Connect with -d postgres, or with the name of a database that exists.
How do I create a database in PostgreSQL from the command line?
Connect to an existing database such as postgres and run CREATE DATABASE appdb. Add OWNER rolename to hand the new database to the application role in the same statement.
Why did POSTGRES_DB not create my database in Docker?
The image reads POSTGRES_DB only when the data directory is empty. On a container whose volume already holds data, create the database with CREATE DATABASE instead.

More decoded errors in the Fixes category. If the server rejects the user name before it gets this far, see role "app" does not exist.