You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a copy of a troubleshooting article on Supabase's docs site. It may be missing some details from the original. View the original article.
A migration that adds an RLS policy to realtime.messages fails:
ERROR: 42501: must be owner of table messages
Cause
realtime.messages is owned by an internal role, supabase_realtime_admin. The postgres role is not a member of it and is not a superuser.
Policies still work because of supautils, the extension that gives the postgres role its elevated permissions on a Supabase project. It lets postgres run create policy, alter policy, and drop policy on a fixed list of tables it does not own, and realtime.messages is on that list. The list covers policy statements only, so ALTER TABLE is still refused.
The failing statement is usually not the create policy. It's an ALTER TABLE earlier in the same migration:
The first one is the common case. RLS is already enabled on realtime.messages, and Postgres checks ownership before it checks whether the setting would change, so the statement fails on every project.
A failed statement aborts the transaction, so Postgres skips everything after it, including the create policy. supabase db push runs each migration file in one transaction, so the file rolls back and nothing is written to supabase_migrations.schema_migrations.
Fix
Remove the ALTER TABLE line. Keep the policy:
create policy "authenticated can read messages on room-1"on"realtime"."messages"
for select
to authenticated
using (
(selectrealtime.topic()) ='room-1'
);
Run it from the SQL editor or with supabase db push. Both connect as postgres.
To check that RLS is on, read the catalog instead of setting it:
select relrowsecurity from pg_class whereoid='realtime.messages'::regclass;
What doesn't work
Granting the owning role fails, and support can't grant it either:
grant supabase_realtime_admin to postgres;
-- ERROR: 42501: "supabase_realtime_admin" role memberships are reserved, only superusers can grant them
Restarting the project changes nothing.
Wrapping the ALTER TABLE in a function or a do block changes nothing either. The ownership check still runs, and a security definer function owned by postgres is still not the table owner.
What postgres can do on realtime.messages
The Yes rows are what supautils delegates, plus the privileges granted to postgres directly.
Statement
Allowed
create policy, alter policy, drop policy
Yes
comment on policy
Yes
select, insert
Yes
grant select, grant insert to your own roles
Yes
alter table in any form
No
drop table
No
Creating tables or functions in the realtime schema
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
This is a copy of a troubleshooting article on Supabase's docs site. It may be missing some details from the original. View the original article.
A migration that adds an RLS policy to
realtime.messagesfails:Cause
realtime.messagesis owned by an internal role,supabase_realtime_admin. Thepostgresrole is not a member of it and is not a superuser.Policies still work because of
supautils, the extension that gives thepostgresrole its elevated permissions on a Supabase project. It letspostgresruncreate policy,alter policy, anddrop policyon a fixed list of tables it does not own, andrealtime.messagesis on that list. The list covers policy statements only, soALTER TABLEis still refused.The failing statement is usually not the
create policy. It's anALTER TABLEearlier in the same migration:The first one is the common case. RLS is already enabled on
realtime.messages, and Postgres checks ownership before it checks whether the setting would change, so the statement fails on every project.A failed statement aborts the transaction, so Postgres skips everything after it, including the
create policy.supabase db pushruns each migration file in one transaction, so the file rolls back and nothing is written tosupabase_migrations.schema_migrations.Fix
Remove the
ALTER TABLEline. Keep the policy:Run it from the SQL editor or with
supabase db push. Both connect aspostgres.To check that RLS is on, read the catalog instead of setting it:
What doesn't work
Granting the owning role fails, and support can't grant it either:
Restarting the project changes nothing.
Wrapping the
ALTER TABLEin a function or adoblock changes nothing either. The ownership check still runs, and asecurity definerfunction owned bypostgresis still not the table owner.What postgres can do on realtime.messages
The
Yesrows are whatsupautilsdelegates, plus the privileges granted topostgresdirectly.create policy,alter policy,drop policycomment on policyselect,insertgrant select,grant insertto your own rolesalter tablein any formdrop tablerealtimeschemaSee Realtime Authorization for writing the policies.
All reactions