This error occurs when attempting to drop a PostgreSQL role that still has privileges granted on database objects. PostgreSQL prevents the role from being dropped to maintain security and ownership integrity.
The 2B000 error code indicates that dependent privilege descriptors are still present when you attempt to drop a role (user or group). This is PostgreSQL's way of protecting against accidental loss of access control settings. When you grant a role privileges on database objects (tables, schemas, functions, etc.), PostgreSQL creates privilege descriptors that track these permissions. Even if the role doesn't own any objects, it may still have been granted SELECT, INSERT, UPDATE, DELETE, or other privileges on objects owned by other roles. PostgreSQL prevents you from dropping the role until these privilege descriptors are cleaned up. This error is distinct from 2BP01 (dependent_objects_still_exist), which occurs when the role owns objects. Error 2B000 specifically relates to privileges granted to the role on objects it doesn't own.
Query the PostgreSQL system catalogs to find what privileges the role has:
-- Find table/view privileges
SELECT
schemaname,
tablename,
privilege_type
FROM information_schema.table_privileges
WHERE grantee = 'role_name';
-- Find schema privileges
SELECT
nspname AS schema_name,
nspacl AS acl
FROM pg_namespace
WHERE nspacl::text LIKE '%role_name%';
-- Find database privileges
SELECT
datname,
datacl
FROM pg_database
WHERE datacl::text LIKE '%role_name%';This will show you exactly what permissions need to be removed.
The simplest approach is to use DROP OWNED BY to remove all privileges for the role in the current database:
-- Connect to the database
\c your_database
-- Drop all privileges and owned objects
DROP OWNED BY role_name;Important: This must be run in EACH database where the role has privileges. REASSIGN OWNED and DROP OWNED cannot access objects in other databases.
-- List all databases
\l
-- For each database:
\c database1
DROP OWNED BY role_name;
\c database2
DROP OWNED BY role_name;After running DROP OWNED in all databases, you can safely drop the role:
DROP ROLE role_name;If you want more control over which privileges are removed, revoke them explicitly:
-- Revoke table privileges
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM role_name;
-- Revoke schema usage
REVOKE USAGE ON SCHEMA public FROM role_name;
-- Revoke database privileges
REVOKE ALL PRIVILEGES ON DATABASE your_database FROM role_name;
-- Revoke sequence privileges
REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM role_name;
-- Revoke function privileges
REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public FROM role_name;Repeat for each schema and database where the role has privileges, then drop the role:
DROP ROLE role_name;If the role also owns objects (causing error 2BP01 in addition to 2B000), you must reassign ownership before dropping privileges:
-- First reassign ownership of all objects
REASSIGN OWNED BY old_role TO new_role;
-- Then drop privileges
DROP OWNED BY old_role;
-- Finally drop the role
DROP ROLE old_role;The order is critical: REASSIGN OWNED first, then DROP OWNED, then DROP ROLE.
Multi-database environments: The most common mistake is forgetting that DROP OWNED BY and REASSIGN OWNED only affect the current database. If your PostgreSQL cluster has multiple databases, you must connect to each one and run the cleanup commands separately.
Default privileges: If the role has default privileges configured (ALTER DEFAULT PRIVILEGES), these won't prevent the role from being dropped, but they should be cleaned up for good hygiene:
ALTER DEFAULT PRIVILEGES FOR ROLE old_role REVOKE ALL ON TABLES FROM old_role;Role memberships: Unlike object ownership and privileges, role memberships (GRANT role_a TO role_b) are automatically cleaned up when you DROP ROLE. You don't need to manually revoke these.
RDS and managed services: On AWS RDS, Azure Database for PostgreSQL, or other managed services, you may need superuser privileges to drop certain roles. If you encounter permission errors, ensure you're connected as the master user or a role with sufficient privileges.
Cascade considerations: While DROP OWNED BY doesn't have a CASCADE option, be aware that it will drop dependent objects like views that depend on tables owned by the role. Always test in a non-production environment first.
ERROR: syntax error at end of input
Syntax error at end of input in PostgreSQL
Bind message supplies N parameters but prepared statement requires M
Bind message supplies N parameters but prepared statement requires M in PostgreSQL
Multidimensional arrays must have sub-arrays with matching dimensions
Multidimensional arrays must have sub-arrays with matching dimensions
ERROR: value too long for type character varying
Value too long for type character varying
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL