How to Fix PostgreSQL Error: Role Does Not Exist

FATAL: role "<name>" does not exist (SQLSTATE 42704, condition undefined_object) is raised when a client tries to authenticate as a PostgreSQL role that has no entry in the cluster's role catalog (pg_authid / pg_roles). The same error appears at SQL level - ERROR: role "<name>" does not exist - when a GRANT, ALTER ROLE, SET ROLE, or ownership statement names a missing role. In both cases the role name is not present in this PostgreSQL cluster.

What This Error Means

PostgreSQL stores all login and group identities as rows in pg_authid. The catalog is cluster-wide, not per-database: a role created in one database is visible from every database in the same cluster. The error appears in two contexts. At connection time, the authentication code checks the supplied user against pg_authid before evaluating pg_hba.conf - a missing role produces a FATAL and the client never sees a session. At runtime, SQL statements that reference a role name (GRANT ... TO, ALTER TABLE ... OWNER TO, SET ROLE) raise 42704 and abort.

Role names follow the same identifier rules as table names: case-folded to lowercase unless double-quoted at creation. A role created with CREATE ROLE "MyApp" is invisible to psql -U myapp and vice versa.

Common Causes

  1. The role was never created in this cluster - confirm with SELECT rolname FROM pg_roles WHERE rolname = '<name>';.
  2. Peer authentication is in use and the OS username has no matching Postgres role - check the local lines in pg_hba.conf.
  3. Wrong cluster targeted - a second PostgreSQL instance on a different port has its own role catalog. Verify with pg_lsclusters or SHOW port;.
  4. Case-folded mismatch: role created as "AdminUser" but client connects as adminuser - check pg_roles for the exact spelling.
  5. Role was dropped or expired (VALID UNTIL in the past) - check rolvaliduntil in pg_roles.
  6. Restored a single database with pg_restore without first restoring globals - role definitions live in pg_dumpall -g output, not per-database dumps.
  7. Application using a stale connection string after a role rename.

How to Fix role does not exist

  1. Confirm whether the role exists in the cluster. Connect as a superuser and check the catalog:

    SELECT rolname, rolcanlogin, rolvaliduntil
    FROM pg_roles
    WHERE rolname ILIKE '<name>';
    

    If the row is missing, the role has never been created in this cluster.

  2. Create the missing login role. CREATE USER is shorthand for CREATE ROLE ... LOGIN:

    CREATE ROLE app_user LOGIN PASSWORD '<strong-password>';
    GRANT CONNECT ON DATABASE mydb TO app_user;
    GRANT USAGE ON SCHEMA public TO app_user;
    
  3. Fix peer authentication mismatches. For local connections using peer, the OS user must have a matching PostgreSQL role:

    sudo -u postgres createuser --pwprompt $(whoami)
    

    Or change the auth method in pg_hba.conf:

    # TYPE  DATABASE  USER  ADDRESS  METHOD
    local   all       all            scram-sha-256
    

    Then sudo systemctl reload postgresql.

  4. Verify you are connected to the right cluster. Multiple Postgres instances on one host each have their own role catalog:

    pg_lsclusters
    sudo -u postgres psql -p 5433 -c '\du'
    
  5. Match the exact case if the role was quoted at creation. Double-quote the role name in the connection string and in SQL:

    psql "postgresql://AdminUser@localhost/mydb"
    
    GRANT pg_read_all_data TO "AdminUser";
    
  6. Restore globals when migrating a cluster. A per-database pg_restore does not include roles. Use pg_dumpall --globals-only to capture and replay role definitions:

    pg_dumpall -h source --globals-only > globals.sql
    psql -h target -f globals.sql
    
  7. Reset an expired role. Setting VALID UNTIL 'infinity' or a future date re-enables the role:

    ALTER ROLE app_user VALID UNTIL 'infinity';
    

Catch role does not exist Errors Before They Hit Production

Pulse provides AI-powered observability for PostgreSQL alongside Elasticsearch, ClickHouse, and Kafka. For SQLSTATE 42704 undefined_object errors on role lookups, Pulse:

  • Tracks FATAL: role "..." does not exist events in the server log alongside pg_stat_activity connection attempts, grouped by role and client IP, so a credential rotation that missed one application instance is immediately visible
  • Correlates the error with recent role/grant changes, pg_hba.conf reloads, and application deploys so root cause maps to the specific change (a DROP ROLE ahead of dependent grants, a renamed role, a peer auth line that no longer matches the OS user) instead of a generic auth failure
  • Flags role and grant drift across replicas, standby clusters, and environments - a pg_restore that skipped pg_dumpall --globals-only leaves a cluster with no roles, which Pulse surfaces before the first connection attempt fails

Set log_connections = on so every failed authentication lands in the log, then alert on any non-zero rate of 42704.

Connect your Postgres cluster to surface issues like this proactively.

Preventive Measures

  • Manage roles through migrations or a config-management tool (Terraform postgresql_role, Ansible postgresql_user) so role state matches code.
  • Avoid quoted mixed-case role names. Stick to lowercase; the case-sensitivity surprise is not worth the cosmetics.
  • Use pg_dumpall --globals-only in your backup schedule so restores include roles, not just data.
  • Document role creation and rotation in the runbook for the database, including the exact SQL.

Frequently Asked Questions

Q: What is SQLSTATE 42704 in PostgreSQL?
A: 42704 is the undefined_object SQLSTATE. PostgreSQL raises it when a SQL statement references a database object (role, type, collation, or operator) that does not exist. For roles specifically, the message is role "<name>" does not exist.

Q: Why does psql work as postgres but fail as my own user?
A: Local connections almost always use peer authentication, which maps to the OS user. If your OS account has no matching PostgreSQL role, the lookup fails. Create the role with sudo -u postgres createuser $(whoami), or change the local auth method to scram-sha-256.

Q: What is the difference between a user and a role in PostgreSQL?
A: They are the same database object. CREATE USER is an alias for CREATE ROLE ... LOGIN. A role without LOGIN behaves as a group; roles with LOGIN can authenticate.

Q: Can a role exist in one database but not another?
A: No. Roles are cluster-wide. Once created, a role is visible from every database in the same PostgreSQL cluster. Permissions per database are separate, but the role identity is shared.

Q: How do I rename a role without breaking dependent objects?
A: Use ALTER ROLE old_name RENAME TO new_name;. Object ownership and grants follow the rename automatically because they reference the role's OID, not its name. Update connection strings in applications after the rename.

Q: Why is my role rejected even though I just created it?
A: Two common causes: the role was created without LOGIN (so it cannot authenticate; add ALTER ROLE name LOGIN), or pg_hba.conf has no matching line for the (database, user, address) tuple, producing a different error. Tail the server log to see which.

Q: How can I detect PostgreSQL role does not exist errors before they break the application?
A: Enable log_connections and treat the 42704 rate as an SLI. Pulse aggregates FATAL: role "..." does not exist events by role and client IP, correlates spikes with credential rotations and pg_hba.conf reloads, and flags role drift across replicas - so a missed application instance after a rotation surfaces before it turns into a customer-visible outage.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.