Skip to content

Fix: PostgreSQL FATAL: role "username" does not exist

FixDevs ·

Quick Answer

How to fix PostgreSQL FATAL role does not exist error caused by missing database roles, peer authentication, wrong usernames, and platform-specific installation defaults.

The Error

You try to connect to PostgreSQL and get:

psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed:
FATAL: role "ubuntu" does not exist

Or variations:

FATAL: role "root" does not exist
FATAL: role "myuser" does not exist
psql: FATAL: role "postgres" does not exist
django.db.utils.OperationalError: FATAL: role "app_user" does not exist

PostgreSQL refused the connection because the database role (user) you are trying to authenticate as does not exist in the PostgreSQL server.

Why This Happens

PostgreSQL uses roles for authentication. Every connection must specify a role name. When you run psql without specifying a user, PostgreSQL defaults to your operating system username. If your OS username is ubuntu, root, or john, PostgreSQL looks for a role with that name — and if it doesn’t exist, you get this error.

Common causes:

  • Running psql as your OS user without a matching role. Your OS user is ubuntu but PostgreSQL only has the postgres role.
  • Fresh installation. PostgreSQL creates only the postgres superuser role by default. No other roles exist until you create them.
  • Wrong username in connection string. Your application’s DATABASE_URL specifies a role that was never created.
  • Docker container setup. The container only has the default role unless you configure POSTGRES_USER.
  • Peer authentication. PostgreSQL is configured to match the OS username to the database role name, and they don’t match.

Fix 1: Connect as the postgres Superuser First

On most installations, the only role that exists initially is postgres. Connect as that user first:

sudo -u postgres psql

This switches to the postgres OS user and runs psql, which connects as the postgres role via peer authentication.

Once connected, you can create the role you need:

CREATE ROLE myuser WITH LOGIN PASSWORD 'mypassword';

Or with additional privileges:

CREATE ROLE myuser WITH LOGIN PASSWORD 'mypassword' CREATEDB;

Then create a database for the user:

CREATE DATABASE mydb OWNER myuser;

Exit with \q and connect as the new user:

psql -U myuser -d mydb -h localhost

Pro Tip: Using -h localhost forces TCP/IP connection with password authentication, bypassing peer authentication. Without it, psql uses the Unix socket and peer auth, which requires the OS username to match the role name.

Fix 2: Create a Role Matching Your OS Username

If you want psql to work without specifying -U, create a role that matches your OS username:

# Check your OS username
whoami
# Output: ubuntu

# Create a matching role
sudo -u postgres createuser --interactive ubuntu

The --interactive flag prompts you for options:

Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) n

Then create a database with the same name:

sudo -u postgres createdb ubuntu

Now psql works without any flags:

psql

PostgreSQL defaults to your OS username for both the role and the database.

Fix 3: Fix the Connection String

If the error comes from an application, check the database connection string:

postgresql://myuser:mypassword@localhost:5432/mydb

Verify that:

  1. The role myuser exists — run \du in psql to list all roles.
  2. The password is correct — reset it with ALTER ROLE myuser WITH PASSWORD 'newpassword';.
  3. The database mydb exists — run \l in psql to list all databases.

Django settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydb',
        'USER': 'myuser',        # This role must exist
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

Rails database.yml:

default: &default
  adapter: postgresql
  username: myuser    # This role must exist
  password: mypassword
  host: localhost

If the connection itself fails before authentication, see Fix: PostgreSQL connection refused.

Fix 4: Fix pg_hba.conf Authentication

PostgreSQL’s pg_hba.conf file controls who can connect and how they authenticate. Common authentication methods:

MethodHow it works
peerOS username must match database role name
md5Password authentication (hashed)
scram-sha-256Password authentication (more secure)
trustNo authentication (dangerous)
identLike peer, but over TCP

Find your pg_hba.conf:

sudo -u postgres psql -c "SHOW hba_file;"

Common location: /etc/postgresql/16/main/pg_hba.conf

The peer authentication issue:

If pg_hba.conf has:

local   all   all   peer

Then every local connection requires the OS username to match the PostgreSQL role name. Either create a matching role (Fix 2) or change peer to md5 or scram-sha-256:

local   all   all   scram-sha-256

Reload PostgreSQL after editing:

sudo systemctl reload postgresql

Common Mistake: Editing pg_hba.conf but forgetting to reload PostgreSQL. The changes only take effect after a reload (systemctl reload) or restart (systemctl restart). A restart disconnects existing clients; a reload does not.

Fix 5: Fix Docker PostgreSQL Roles

In Docker, the default role is controlled by the POSTGRES_USER environment variable:

docker run -e POSTGRES_USER=myuser -e POSTGRES_PASSWORD=mypassword -e POSTGRES_DB=mydb -p 5432:5432 postgres:16

If you omit POSTGRES_USER, the default role is postgres.

Docker Compose:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword
      POSTGRES_DB: mydb
    ports:
      - "5432:5432"

Existing container with wrong role:

If the container was already created with a different user, the data volume retains the old configuration. Delete the volume and recreate:

docker compose down -v  # -v removes volumes
docker compose up -d

Warning: -v deletes all data in the PostgreSQL volume. Only do this for development databases.

If you need to add a role to an existing container:

docker exec -it my-postgres psql -U postgres -c "CREATE ROLE myuser WITH LOGIN PASSWORD 'mypassword';"
docker exec -it my-postgres psql -U postgres -c "CREATE DATABASE mydb OWNER myuser;"

Fix 6: Fix macOS Homebrew PostgreSQL

Homebrew PostgreSQL on macOS creates a superuser role matching your macOS username automatically. But if you run psql as a different user or the role was deleted:

Check the default role:

whoami
# Output: john

psql -l  # List databases — uses "john" as the role

If the role was deleted or never created:

createuser --superuser $(whoami)
createdb $(whoami)

If postgres role doesn’t exist (common with Homebrew):

createuser --superuser postgres

Homebrew installs do not always create the postgres role, which trips up tutorials and tools that assume it exists.

Fix 7: Fix Role Permissions

After creating a role, you might need to grant it access to existing databases and schemas:

-- Connect as postgres superuser
sudo -u postgres psql

-- Grant connection to a database
GRANT CONNECT ON DATABASE mydb TO myuser;

-- Connect to the database
\c mydb

-- Grant usage on schema
GRANT USAGE ON SCHEMA public TO myuser;

-- Grant access to all existing tables
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO myuser;

-- Grant access to future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO myuser;

-- Grant sequence usage (needed for auto-increment columns)
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO myuser;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE ON SEQUENCES TO myuser;

If the role exists but can’t see tables, the issue is schema permissions. This manifests as relation does not exist errors.

Fix 8: List and Manage Existing Roles

List all roles:

\du

Or:

SELECT rolname, rolsuper, rolcreatedb, rolcreaterole, rolcanlogin
FROM pg_roles
ORDER BY rolname;

Rename a role:

ALTER ROLE old_name RENAME TO new_name;

Drop a role:

-- First reassign owned objects
REASSIGN OWNED BY old_role TO postgres;

-- Then drop
DROP ROLE old_role;

You cannot drop a role that owns objects. Reassign or drop the owned objects first.

Grant superuser:

ALTER ROLE myuser WITH SUPERUSER;

Remove superuser (for security):

ALTER ROLE myuser WITH NOSUPERUSER;

Still Not Working?

If the role exists but you still get this error:

Check for case sensitivity. PostgreSQL folds unquoted identifiers to lowercase. If the role was created with double quotes (CREATE ROLE "MyUser"), you must always use quotes. Check with \du — the role name is shown exactly as stored.

Check the PostgreSQL port. If multiple PostgreSQL instances are running, you might be connecting to the wrong one:

psql -U myuser -h localhost -p 5432
psql -U myuser -h localhost -p 5433  # Another instance

Check pg_ident.conf for ident mapping. If pg_hba.conf uses peer map=mymap, the pg_ident.conf file controls which OS users map to which database roles. An incorrect mapping causes this error.

Check for connection pooler interference. PgBouncer or Pgpool-II might authenticate against their own user list, not PostgreSQL’s. Check the pooler’s auth_file or userlist.txt.

Check if PostgreSQL is actually running:

systemctl status postgresql

If the service is down, you get a connection error rather than a role error. But if a different database engine is running on the same port, you might get unexpected authentication errors.

If the connection itself fails rather than authentication, see Fix: PostgreSQL connection refused. If the role exists but queries fail because tables are missing, see Fix: relation does not exist.

For similar authentication issues in MySQL, see Fix: MySQL access denied for user.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles