Přejít na obsah

Supabase 42501 permission denied: je to grant, ne RLS

Supabase

Zobrazit jako MarkdownOtevřít v ClaudeOtevřít v ChatGPTOtevřít v Perplexity

Otázka se zkopíruje také. Pokud se chat otevře prázdný, vložte ji.

TL;DR

42501 permission denied for table … znamená, že role nemá na tabulku grant, takže Postgres zastaví požadavek dřív, než se spustí jakákoli politika RLS. Od 30. října 2026 Supabase na stávajících projektech přestává tabulky v public automaticky zpřístupňovat, takže tabulky vytvořené později odpovídají 42501, dokud jim nedáte grant. Oprava jsou tři příkazy dohromady: grant pro operace, které role potřebuje, enable row level security a politika. Samotný grant bez RLS otevře tabulku všem.

Postavil jsem bezplatný bezpečnostní checker pro Supabase, který čte granty na každé zpřístupněné tabulce, a 42501 je chyba, na kterou lidé narazí, když jsou granty špatně na opačnou stranu: příliš málo místo příliš mnoho. Tady je, co znamená a co jsem viděl, když jsem ji reprodukoval.

Co znamená chyba 42501 v Supabase?

42501 je kód Postgresu pro nedostatečné oprávnění. Postgres kontroluje dvě vrstvy, než se klient dotkne tabulky: granty rozhodují, zda role smí operaci vůbec provést, a politiky RLS rozhodují o řádcích. Chybějící grant selže první, jako chyba. Politika, která nic neodpovídá, selže tiše, jako prázdný seznam. Když tedy vidíte 42501, dívejte se na granty, ne na politiky.

PostgREST, Data API za supabase-js, chybu předá dál s nápovědou. Na mém lokálním stacku (Supabase CLI 2.109.1, Postgres 17.6, PostgREST 14.14) vrátil požadavek s publishable key na tabulku bez grantu pro anon HTTP 401 a:

{
  "code": "42501",
  "details": null,
  "hint": "Grant the required privileges to the current role with: GRANT SELECT ON public.orders TO anon;",
  "message": "permission denied for table orders"
}

Proč nové tabulky dostávají 42501 po 30. říjnu 2026?

Dosud dostala nová tabulka v public přes výchozí oprávnění select, insert, update a delete pro anon, authenticated a service_role, takže byla dosažitelná přes Data API hned po vytvoření, chráněná či ne. Changelog Supabase tato výchozí nastavení odstraňuje: volitelně od 28. dubna 2026, jako výchozí pro nové projekty od 30. května 2026 a na všechny stávající projekty se použije 30. října 2026. Stávající tabulky si granty ponechají.

Co dalšího přepnutí rozbije a jak projekt zkontrolovat předem: Supabase 30. října: co se rozbije a jak to ověřit.

Stejnou změnu jsem aplikoval na svůj lokální projekt pomocí dvou příkazů alter default privileges … revoke z changelogu a pak vytvořil novou tabulku invoices:

Co odpoví nová tabulka po 30. říjnu 2026. Lokální Supabase s novými výchozími oprávněními, vždy jeden požadavek. Publishable key, bez grantu: create table → bez grantu → 42501, HTTP 401; Secret key, bez grantu: create table → bez grantu → 42501, HTTP 403; Po grant select a zapnutí RLS: grant select → RLS zapnuté → 0 řádků, HTTP 200.
Moje reprodukce na lokálním Supabase s výchozími oprávněními z changelogu Supabase, 23. října 2026.
Požadavek na novou tabulku Výsledek
Publishable key, bez grantu HTTP 401, 42501, nápověda GRANT SELECT ON public.invoices TO anon;
Secret key, bez grantu HTTP 403, 42501, nápověda … TO service_role;
Publishable key, po grant select a enable row level security HTTP 200, [], dokud politika nepovolí řádky

Dvě věci mě překvapily. Secret key je odmítnut také: service_role obchází RLS, ale grant stejně potřebuje, takže Edge Function nebo serverová úloha, která zapisuje do nové tabulky, se rozbije stejně. A revoke bere zpět jen ty čtyři operace: nová tabulka přesto přišla s REFERENCES, TRIGGER a TRUNCATE pro anon, authenticated a service_role. Na TRUNCATE se žádná politika nevztahuje.

Jak opravit 42501, aniž otevřete tabulku?

Berte grant, RLS a politiku jako jednu změnu v jedné migraci a každé roli dejte jen to, co potřebuje:

revoke all on table public.invoices from anon, authenticated;
grant select, insert, update on table public.invoices to authenticated;
grant select, insert, update, delete on table public.invoices to service_role;

alter table public.invoices enable row level security;

create policy "Owners read their invoices"
on public.invoices for select
to authenticated
using ((select auth.uid()) = user_id);

Úvodní revoke all smaže TRUNCATE, TRIGGER a REFERENCES, které přišly s tabulkou. Na 42501 neodpovídejte příkazem grant all on all tables in schema public to anon: to je starý výchozí stav zpět, pro všechny tabulky najednou, a každá tabulka bez RLS se stane čitelnou pro kohokoli s vaším veřejným klíčem.

Pokud vaše tabulky vytváří AI nástroj, řekněte mu, ať granty, RLS a politiky vydává ve stejné migraci. Nápověda v chybě je napsaná tak, aby agent mohl grant opravit sám, ale jmenuje jen grant, ne RLS, které by k němu mělo přijít.

Jak to vidí checker?

Čtyři jeho pravidla čtou vrstvu grantů: „Výchozí oprávnění, která otevírají nové objekty API“ označí projekty, které stále automaticky zpřístupňují nové tabulky, „Nepoužívaná oprávnění k zápisu pro anonymní návštěvníky“ najde zápisové granty pro anon, které nepoužívá žádná politika, a „Zbytečná oprávnění k tabulkám pro přihlášené uživatele“ najde TRUNCATE, TRIGGER a REFERENCES jako ty výše. „Politiky, které se nikdy nespustí: role nemá grant“ vypíše tabulky, kde politika uvádí roli, která pro daný příkaz nemá grant, a přesně tak vypadá nová tabulka po 30. říjnu. Proč RLS záleží i po grantu, je v článku jak testovat Supabase RLS a jak vypadají granty a politiky napříč celou aplikací, je v mém checklistu zabezpečení Lovable aplikace.

© 2026 Denys Zaichenko. Původní článek: https://madsalt.tech/cs/notes/supabase-42501-permission-denied/