Replies: 10 comments 4 replies
|
Can you run that SQL from the SQL editor as Postgres? Yes you should be able to add RLS policies but not Alter Table or several other things in the realtime schema. https://github.com/orgs/supabase/discussions/48441 specifically says you can still modify/add policies as Postgres. Not seeing any other reports of this specifically. |
|
Thanks for the suggestion. I tested the exact same SQL directly from the Supabase SQL Editor, running as the The statement executed successfully: Success. No rows returned. The policy was actually created successfully from the SQL Editor. So the SQL itself is valid and can be executed manually as The failure only occurs when the exact same statement is executed through our migration pipeline, where it fails with: SQLSTATE 42501: must be owner of relation messages This suggests the issue is specific to the migration execution context rather than the SQL itself. Do you know what difference in the migration execution context could explain this behaviour? |
|
I do not know much about migrations. It is supposed to run as postgres user I'm pretty sure. Any chance you do a set role in the migration? You might post in the CLI repository issues... https://github.com/supabase/cli/issues Are you running the latest CLI? I'm finding no similar reports. |
|
Thanks for checking. I verified both points:
The same SQL succeeds when executed directly from the Supabase SQL Editor as the The failure only occurs when the identical statement is executed through the migration pipeline, where it fails with: SQLSTATE 42501: must be owner of relation messages So at this point the only difference we can identify is the migration execution context itself. We'll also open an issue in the Supabase CLI repository as you suggested, unless you think this belongs somewhere else. |
|
This is not an ownership or provisioning problem with your project — the owners you printed are the expected ones. It is how PostgreSQL resolves the ownership check for
If Run this to see which case you are in: select pg_has_role(current_user, 'supabase_realtime_admin', 'MEMBER') as can_set_role,
pg_has_role(current_user, 'supabase_realtime_admin', 'USAGE') as inherits_privs;
set role supabase_realtime_admin;
create policy authorize_record_edit_presence
on realtime.messages
for all
to authenticated
using (
realtime.topic() like 'record_edit:%'
and split_part(realtime.topic(), ':', 2)::uuid = public.fn_get_current_user_unit_id()
);
reset role;If One thing worth changing regardless of how the ownership resolves: schema-qualify Your policy body is evaluated later, by Realtime, under whatever Same reasoning applies to the |
|
Yes, I confirmed that. The exact same SQL executes successfully from the Supabase SQL Editor using the The failure only occurs when the identical SQL is executed through Following your suggestion, I opened a dedicated CLI issue with the full reproduction details: Thanks for pointing me in the right direction. |
|
I ran the checks. select
pg_has_role(current_user, 'supabase_realtime_admin', 'MEMBER') as can_set_role,
pg_has_role(current_user, 'supabase_realtime_admin', 'USAGE') as inherits_privs;Result: I also tested: set role supabase_realtime_admin;and got: So it looks like this project does not allow the Given that, should this role membership exist on Cloud projects, or is this project missing the expected provisioning? |
|
Thanks for clarifying. That makes sense regarding However, I'm still trying to understand why the exact same when executed through Is the CLI executing migrations under a different effective role than the SQL Editor, or is there another difference between those execution paths? |
|
That settles it, and it is not your project.
The reason the identical SQL succeeds in the SQL Editor is that the dashboard does not execute over the same connection and privilege path that So the guarantee in #34270 ("create RLS policies ... on realtime.messages") currently holds through the dashboard path only. That mismatch between the documented permission and what the CLI connection can actually do is exactly what supabase/cli#6116 should track, and filing it separately was the right call. To unblock your pipeline meanwhile: apply the policy once from the SQL Editor, then mark that migration as already applied so The migration file stays in version control as the record of intent, and CI stops failing on a statement that connection cannot execute. |
|
Those two results are the interesting part, because together with what you already know they are contradictory:
Both cannot be true for the same role in the same database. The fastest way to see it is to print the identity from both sides and compare, instead of inferring it: select current_user,
session_user,
inet_server_port() as port,
current_setting('is_superuser') as is_superuser,
(select rolbypassrls from pg_roles
where rolname = current_user) as bypassrls,
pg_get_userbyid((select relowner from pg_class
where oid = 'realtime.messages'::regclass)) as table_owner,
pg_has_role(current_user, 'supabase_realtime_admin', 'USAGE') as inherits;Run it once in the SQL Editor, then put the same statement at the top of a throwaway migration and run Two candidates worth expecting: 1. The port. 2. Either way, the result is worth adding to the CLI issue you opened — a reproducible identity diff is a much stronger report than "same SQL, different outcome", and it tells the CLI maintainers immediately whether this is a connection-string default rather than a bug in the migration runner. One more thing worth doing regardless of how this resolves, since it will bite later: select tgname, tgrelid::regclass
from pg_trigger where not tgisinternal and tgrelid = 'realtime.messages'::regclass;If the policy eventually lands, schema-qualify |
Uh oh!
There was an error while loading. Please reload this page.
Summary
I'm trying to enable Realtime Authorization following the official documentation.
A standard SQL migration executed by Supabase CLI fails while creating an RLS policy on
realtime.messageswith:The SQL matches the official documentation, so I'm trying to understand whether:
Environment
SQL executed
Result
The migration fails with:
Diagnostics already performed
Current owners:
No manual ownership changes have ever been executed.
No:
have been attempted.
The migration aborts atomically and no policy is created.
Documentation consulted
Realtime Authorization:
https://supabase.com/docs/guides/realtime/authorization
Supabase announcement (April 2025):
https://github.com/orgs/supabase/discussions/34270
That announcement explicitly says users can still create RLS policies on:
Similar issues
CLI issue:
supabase/cli#3549
CLI issue:
supabase/cli#3070
Both describe ownership-related SQLSTATE 42501 errors on Supabase-managed schemas.
Question
Should creating RLS policies on
realtime.messagesstill work from standard migrations executed aspostgres?Or is there now another officially supported deployment method for Realtime Authorization policies?
A full technical investigation report is attached below, including diagnostics, ownership checks, migration history and references consulted.
INFORME_INCIDENCIA_PASO18_REALTIME_MESSAGES.md
All reactions