How to fix Role already exists in PostgreSQL
This error occurs when you attempt to create a PostgreSQL role (user account) that already exists in the database. Unlike CREATE TABLE, CREATE ROLE has no IF NOT EXISTS clause, so duplicate attempts fail. There are several solutions using PL/pgSQL blocks or conditional checks.
Quick fix
Fixes Role already exists
sudo -u postgres psql -c "\\du"- Check if the role exists before creating
- Use a PL/pgSQL DO block with exception handling
- Use a conditional existence check in PL/pgSQL
- Modify an existing role using ALTER instead of CREATE
sudo -u postgres psql -c "\\du"Role already exists
What this error means
PostgreSQL manages database access through roles, which can be users (with login privileges) or groups. When you execute a CREATE ROLE statement, PostgreSQL checks its system catalog to ensure the role name is unique. If a role with that name already exists, the statement fails immediately. This is a schema-level constraint to prevent duplicate role definitions.
Typical symptoms
- CREATE ROLE command fails with 'Role already exists' error
- Migration scripts or initialization routines fail during database setup
- Attempting to re-run creation scripts that worked previously now fail
- pg_restore or psql -f dump_file commands fail when importing database definitions
- CI/CD pipelines fail when idempotent role creation is attempted
Common causes
- The role was already created in a previous run or by another administrator
- Running the same CREATE ROLE script multiple times without checking for existence
- Restoring a database dump that contains roles that already exist in the target database
- Multiple scripts or tools attempting to create the same role concurrently
- Copying role creation code from another database without verifying the target state
How to fix "Role already exists"
First, verify whether the role already exists in your PostgreSQL instance:
sudo -u postgres psql -c "\\du"Or query directly:
SELECT rolname FROM pg_roles WHERE rolname = 'my_user';If the role appears in the results, it already exists and doesn't need to be created.
Wrap your CREATE ROLE statement in an anonymous code block that catches the duplicate_object exception:
DO $$
BEGIN
CREATE ROLE my_user LOGIN PASSWORD 'my_password';
EXCEPTION
WHEN duplicate_object THEN
RAISE NOTICE 'Role my_user already exists, skipping.';
END
$$;This approach allows the script to continue even if the role exists. The WHEN duplicate_object clause catches the duplicate error and simply logs a notice instead of failing.
For more control, check the pg_roles catalog before attempting creation:
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'my_user') THEN
CREATE ROLE my_user LOGIN PASSWORD 'my_password';
RAISE NOTICE 'Role my_user created.';
ELSE
RAISE NOTICE 'Role my_user already exists.';
END IF;
END
$$;This gives you visibility into whether the role was created or already existed.
If the role exists and you need to change its properties, use ALTER ROLE instead:
ALTER ROLE my_user WITH LOGIN PASSWORD 'new_password';You can change login privileges, password, superuser status, and other attributes without recreating the role. Check the existing role first:
SELECT * FROM pg_roles WHERE rolname = 'my_user';When working with pg_dump, you have options to handle existing roles:
Option 1: Drop existing roles before restoring
psql -U postgres -d your_database -c "DROP ROLE IF EXISTS my_user;"
psql -U postgres -d your_database -f dump.sqlOption 2: Dump without role definitions
pg_dump --no-owner --no-acl source_db > dump.sqlThen roles must exist before you restore:
psql -U postgres -d target_db -f dump.sqlOption 2 is safer for production environments where role management is separate from object ownership.
Advanced notes
Race Conditions: If multiple connections attempt to create the same role simultaneously, one succeeds and others hit the duplicate error. The exception handling approach is safer because it checks and creates in a single atomic transaction.
Idempotent Scripts: For infrastructure-as-code, use the DO block with exception handling approach. This makes scripts idempotent—they can be run repeatedly without side effects, which is important for Kubernetes, Terraform, or other declarative tools.
Cascade Drops: If you need to drop and recreate a role that owns objects, use DROP ROLE IF EXISTS my_user CASCADE; to remove dependent objects first. However, this is destructive and should only be used in development or with explicit intent.
Role Attributes: When creating or modifying a role, consider which privileges it needs: LOGIN (to connect), CREATEDB, CREATEROLE, SUPERUSER, REPLICATION, etc. Different attributes affect how the role can be used throughout your PostgreSQL instance.
Frequently asked questions
- What does "Role already exists" mean?
- PostgreSQL manages database access through roles, which can be users (with login privileges) or groups. When you execute a CREATE ROLE statement, PostgreSQL checks its system catalog to ensure the role name is unique. If a role with that name already exists, the statement fails immediately.
- How do I fix "Role already exists"?
- This error occurs when you attempt to create a PostgreSQL role (user account) that already exists in the database. Unlike CREATE TABLE, CREATE ROLE has no IF NOT EXISTS clause, so duplicate attempts fail. There are several solutions using PL/pgSQL blocks or conditional checks.
- What causes "Role already exists"?
- The role was already created in a previous run or by another administrator Running the same CREATE ROLE script multiple times without checking for existence Restoring a database dump that contains roles that already exist in the target database
- Is the "Role already exists" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.