“Access denied” means the connected role lacks the required privileges on a database object or is blocked by row-level security.
PostgreSQL rejects a statement when the current role has no privilege on the target object or when row-level security (RLS) blocks the row. The server stops the query and returns “ERROR: permission denied for …”.
Run \dp schema.table
in psql
or query pg_catalog.pg_roles
and information_schema.table_privileges
to see who owns the object and which roles have SELECT, INSERT, UPDATE, or DELETE.
Use GRANT
to add rights without changing ownership. Example: give reporting_role read-only access to Orders
and OrderItems
.
GRANT SELECT ON public.Orders, public.OrderItems TO reporting_role;
If the table has a serial or identity column, also grant USAGE
and SELECT
on the sequence or inserts will fail.
“permission denied for table” often means the table is owned by a different user. Connect as the owner or a superuser and run ALTER TABLE … OWNER TO new_owner;
.
Use ALTER DEFAULT PRIVILEGES
so that new tables inherit the correct rights. This prevents forgotten grants during deployments.
Grant EXECUTE
on CREATE FUNCTION
objects. Without it, calling the function raises “permission denied”.
If RLS is ON, even superusers need a matching policy. Use ALTER TABLE … DISABLE ROW LEVEL SECURITY
or define a permissive policy.
Create dedicated roles for apps, follow least privilege, script your grants, and test migrations in staging. Review logs with log_statement = 'ddl'
to spot missing privileges early.
No. You only need to connect as the object owner or a role with GRANT
OPTION on that object.
Row-level security may block the row. Disable RLS or add a policy that matches the session role.
Query pg_class.relowner
joined with pg_roles.rolname
or run \dt+ schema.table
in psql
.