Incident brief
Duplicate object
A CREATE ROLE named a role that already exists. PostgreSQL refused to create a second role under the same name.
What lands in your log
ERROR: role "reporting_ro" already exists
In 10 seconds
- What triggers it
- CREATE ROLE with a name that already exists.
- Fix
- Wrap the CREATE ROLE in a DO block that catches the duplicate_object exception, for idempotent setup scripts.
- Proof
- Reproduced on PostgreSQL 16.14 → Creating a role with a name that already existed was rejected with SQLSTATE 42710. Exactly one role with that name still exists afterward.
Fix
What to do right now
Application-level steps for this error.
- Wrap the CREATE ROLE in a DO block that catches the duplicate_object exception, for idempotent setup scripts.
- Otherwise, check pg_roles first and only create the role if it's missing.
- Don't widen the exception handler to WHEN OTHERS, see the counterexample for what that silently hides.
DO $$ BEGIN
CREATE ROLE reporting_ro;
EXCEPTION WHEN duplicate_object THEN
NULL;
END $$;For this error
See this error live on the server
Run these against the affected instance to confirm the diagnosis before you act.
Resolve the existing object and its relkind before deciding to reuse, rename, or drop it.
Existing object with this name
Replace the literal with the identifier from the error; relkind distinguishes table, index, view, sequence, and partition.
SELECT n.nspname AS schema_name, c.relname, c.relkind
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = '<object_name>'
ORDER BY n.nspname, c.relname
LIMIT 50;Why it happens
What PostgreSQL is telling you
The mechanism behind the error, grounded in the official manual, not paraphrased.
PostgreSQL 16 Documentation, CREATE ROLE, CREATEROLE clause
These clauses determine whether a role will be permitted to create, alter, drop, comment on, and change the security label for other roles.Read the full section on postgresql.org →
The duplicate CREATE ROLE
PostgreSQL found an existing role with the same name and refused to create a second one, role names must be unique across the whole cluster.Confirming exactly one role exists
Exactly one reporting_ro exists, the rejected second CREATE ROLE had no effect.Reproduce & verify
A real, single-session PostgreSQL reproduction
A literal transcript of SQL run against a live PostgreSQL instance in an isolated lab. The commands below are exactly what was executed.
- 1CREATE ROLE with a name that already exists.
- 2PostgreSQL refuses to create a duplicate role.
- 3SQLSTATE 42710 is reported, naming the exact role.
One client: create a role, then try to create another role with the same name.
-- No table needed: this reproduction is about roles, not table schema.
SELECT 'no schema required' AS setup_note;DROP ROLE IF EXISTS reporting_ro;
CREATE ROLE reporting_ro;
CREATE ROLE reporting_ro;SELECT count(*) FROM pg_roles WHERE rolname = 'reporting_ro';What PostgreSQL actually returned
setup_note
--------------------
no schema required
(1 row)NOTICE: role "reporting_ro" does not exist, skipping
DROP ROLE
CREATE ROLE
ERROR: role "reporting_ro" already exists count
-------
1
(1 row)The DO-block fix was tested by running it twice in a row against the same already-existing role, to prove it's genuinely idempotent, not just error-free once.
Without this
Above: a bare second CREATE ROLE is rejected.
With this, tested
Below: the same CREATE ROLE, wrapped to catch duplicate_object, succeeds silently both times.
- A second operational test: exact SQL, raw output, measured result, and engineer notes
- Fix that hides a real permission error, not just the duplicate: exact SQL, output, and verdict
- A manual-grounded production interpretation of the lab result
Card required. Cancel before day 7 and you are not charged.
Connected
Everything this error touches
Every page this SQLSTATE connects to: the concept that explains it, the runbooks that fix it, the parameters you tune to prevent it, and the sibling errors it travels with. All real cross-references. Jump straight in, or open the full interactive map.
Verification
- Last verified
- 2026-07-16 (Docker lab, PostgreSQL 16.14)
- Verification scope
- Verified against PostgreSQL 16.14 in an isolated lab environment
- Audit status
- reviewed
Went further?
Pro unlocks the second lab proof
Free page stops the bleeding. Pro adds the operational test, SQLSTATE audit, and deeper evidence, same error, more certainty.