Seeing the FATAL: permission denied for database "dbname" error can be a major roadblock when trying to access your PostgreSQL data. This message typically triggers during the connection startup phase, signaling that while your login credentials (username and password) might be valid and accepted by the server, your specific database role lacks the necessary authorization to enter the target database.
Resolving this issue requires looking beyond simple login credentials and examining the internal privilege chain of the database cluster. Whether the cause is a missing SQL grant or a restrictive configuration in the pg_hba.conf authentication settings, this guide provides three reliable methods to diagnose and restore access quickly.
Table of Contents
Key Takeaways for Troubleshooting Database Access
- CONNECT privilege → The fundamental SQL requirement for database entry. Even if a role exists in the cluster, it must be explicitly granted the right to connect to specific databases.
- Layered Security → Database access is checked at two stages: first through the
pg_hba.conffile for network-level permission, and second via the internal SQL grant system. - PUBLIC role → A special marker representing every role. By default, PostgreSQL often grants CONNECT to PUBLIC, but security-conscious administrators frequently REVOKE this to tighten access.
- Superuser status → A role with the
SUPERUSERattribute bypasses all internal permission checks except for the basic right to log in, making it a useful tool for emergency access.
Method 1: Granting Direct SQL-Level CONNECT Privileges
The most common cause of this error is that the user has not been granted the CONNECT right at the database level. In PostgreSQL, having a LOGIN account does not automatically authorize you to enter every database in the cluster.
How to Apply the Fix: An administrator or the database owner must execute a GRANT statement. To allow a user named luca to access forumdb, run: GRANT CONNECT ON DATABASE forumdb TO luca;.
Verification: After running the command, you can verify the update by using the \l meta-command in the psql terminal. Look for the c flag (representing Connect) in the “Access privileges” column next to your database. For a deeper look at managing these statements, see the PostgreSQL GRANT Statement: A Complete Guide.
Method 2: Managing Access Through Role Membership
Managing permissions for dozens of individual users can become cumbersome. PostgreSQL allows you to group users into group roles, where privileges are granted once to the group and inherited by its members.
How to Set Up a Connection Group:
- Create a group role:
CREATE ROLE connection_group NOLOGIN; - Grant database access to the group:
GRANT CONNECT ON DATABASE forumdb TO connection_group; - Add your user to the group:
GRANT connection_group TO luca;.
If the membership is granted with the INHERIT attribute (the default), the user will automatically gain access without needing to issue an explicit SET ROLE command. To understand the difference between active login roles and inherited rights, explore Understanding PostgreSQL Access Control: Login Roles vs. Connect Privileges.
Step-by-Step Process to Restore Database Access
- Identify the Target Role: Use the
\ducommand in psql to verify the exact name and attributes of the user facing the error. - Log in as a Superuser: Connect to the cluster using a high-privilege account like
postgresto perform administrative changes. - Verify Existing Database Rights: Run the following SQL function to programmatically confirm if the user lacks access:
SELECT has_database_privilege('username', 'dbname', 'CONNECT');. - Execute the Grant: Apply the necessary rights using the
GRANT CONNECTsyntax described in Method 1. - Check the pg_hba.conf File: Ensure that a line exists allowing that specific connection type, user, and database combination from the client’s IP address.
- Reload Configuration: If you modified the config file, run
SELECT pg_reload_conf();to apply changes without a full restart.
Summary of Database-Level Privileges
| Privilege | ACL Flag | Purpose |
|---|---|---|
CONNECT | c | Allows the role to open a connection to the database. |
CREATE | C | Allows the role to create new schemas or extensions in the database. |
TEMPORARY | T | Allows the creation of temporary tables during the session. |
ALL | — | A shortcut to grant all of the above rights simultaneously. |
FAQs
Does a Superuser need a CONNECT grant? No. A role with the SUPERUSER attribute bypasses all permission checks, including database-level connect rights.
Why can I connect now but still cannot see any tables? The CONNECT privilege only gets you through the front door. To see or query tables, you also need the USAGE privilege on the Schema and SELECT rights on the individual tables.
See also: Mastering the Linux Command Line — Your Complete Free Training Guide
What if I want to kick all users out of a database? You can revoke the connect privilege from the PUBLIC role to prevent any new connections during maintenance.



