本文へスキップ

Supabase 42501 permission denied:原因はgrantでRLSではない

Supabase

Markdownで表示Claudeで開くChatGPTで開くPerplexityで開く

質問もコピーされます。チャットが空で開いた場合は貼り付けてください。

TL;DR

42501 permission denied for table …は、そのロールにテーブルへのgrantがないことを意味します。そのため、RLSポリシーが実行される前に、Postgresがリクエストを止めます。2026年10月30日から、Supabaseは既存プロジェクトのpublicの新しいテーブルに自動でgrantしなくなります。それ以降に作られたテーブルは、grantするまで42501を返します。直し方は、3つの文をセットにすることです。ロールに必要な操作へのgrant、enable row level security、そしてポリシーです。RLSなしでgrantだけを行うと、テーブルは全員に開いてしまいます。

私は、公開されているすべてのテーブルのgrantを読む無料のSupabaseセキュリティチェッカーを作りました。42501は、grantが逆方向に間違っているとき、つまり多すぎるのではなく少なすぎるときに出るエラーです。ここでは、それが何を意味するかと、再現して分かったことを説明します。

Supabaseのエラー42501は何を意味する?

42501は、権限不足を表すPostgresのコードです。クライアントがテーブルに触れる前に、Postgresは2つの層を確認します。grantは、そのロールがその操作を実行できるかを決め、RLSポリシーは、どの行かを決めます。grantがなければ、まずエラーとして失敗します。どの行にも一致しないポリシーは、空のリストとして静かに失敗します。だから42501を見たら、ポリシーではなくgrantを見てください。

supabase-jsの裏にあるData APIのPostgRESTは、エラーをヒント付きでそのまま返します。私のローカルスタック(Supabase CLI 2.109.1、Postgres 17.6、PostgREST 14.14)では、anonへのgrantがないテーブルにpublishable keyでリクエストすると、HTTP 401と次の内容が返りました。

{
  "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"
}

2026年10月30日以降、新しいテーブルで42501が出るのはなぜ?

これまで、publicの新しいテーブルには、デフォルト権限によりanon、authenticated、service_roleへselect、insert、update、deleteが付与されていました。そのため、保護されているかどうかにかかわらず、作成した瞬間からData API経由で到達できました。Supabaseのchangelogは、このデフォルトを取り除きます。2026年4月28日からオプションで、2026年5月30日から新規プロジェクトのデフォルトに、そして2026年10月30日にすべての既存プロジェクトへ適用されます。既存のテーブルはgrantを維持します。

切り替えで他に何が壊れるか、事前の確認方法はSupabase 10月30日のgrant変更:壊れる点と確認方法にまとめました。

changelogにある2つのalter default privileges … revokeの文で、同じ変更を自分のローカルプロジェクトに適用し、新しいテーブルinvoicesを作りました。

2026年10月30日以降、新しいテーブルが返すもの。新しいデフォルト権限のローカルSupabase、リクエストは各1回。Publishable key、grantなし:create table → grantなし → 42501, HTTP 401、Secret key、grantなし:create table → grantなし → 42501, HTTP 403、grant selectとRLS有効化のあと:grant select → RLSオン → 0行、HTTP 200。
Supabaseのchangelogにあるデフォルト権限を適用したローカルのSupabaseスタックでの私の再現、2026年10月23日。
新しいテーブルへのリクエスト 結果
Publishable key、grantなし HTTP 401、42501、ヒントはGRANT SELECT ON public.invoices TO anon;
Secret key、grantなし HTTP 403、42501、ヒントは… TO service_role;
Publishable key、grant selectとenable row level securityのあと HTTP 200、ポリシーが行を許可するまで[]

驚いたことが2つあります。1つ目は、secret keyも拒否されることです。service_roleはRLSを迂回しますが、それでもgrantは必要なので、新しいテーブルに書き込むEdge Functionやサーバーのジョブも、同じように壊れます。2つ目は、revokeで取り消されるのはその4つの操作だけだということです。新しいテーブルには、anon、authenticated、service_role向けのREFERENCES、TRIGGER、TRUNCATEが付いたままでした。TRUNCATEにはどのポリシーも適用されません。

テーブルを開けずに42501を直すには?

grant、RLS、ポリシーを1つの変更として、1つのマイグレーションにまとめ、各ロールには必要なものだけを付与します。

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);

最初のrevoke allで、テーブルと一緒に付いてきたTRUNCATE、TRIGGER、REFERENCESを消します。42501にgrant all on all tables in schema public to anonで答えてはいけません。それは古いデフォルトを、すべてのテーブルに一度に戻すことで、RLSのないテーブルは、公開キーを持つ誰にでも読めるようになります。

AIツールがテーブルを作るなら、grant、RLS、ポリシーを同じマイグレーションで出力するよう指示してください。エラーのヒントは、エージェントがgrantを自分で直せるように書かれていますが、ヒントが挙げるのはgrantだけで、一緒に付けるべきRLSには触れていません。

チェッカーはこれをどう見る?

チェッカーの4つのルールがgrantの層を読みます。「新しいオブジェクトを API に開くデフォルト権限」は、新しいテーブルを今も自動でgrantするプロジェクトを指摘します。「匿名の訪問者に残っている未使用の書き込み権限」は、どのポリシーも使っていないanonの書き込みgrantを見つけます。「サインイン中のユーザーに不要なテーブル権限」は、上のようなTRUNCATE、TRIGGER、REFERENCESを見つけます。「実行されないポリシー:ロールに権限がない」は、そのコマンドのgrantを持たないロールをポリシーが指定しているテーブルを一覧にします。10月30日以降の新しいテーブルは、まさにこの状態です。grantのあともRLSが重要な理由はSupabase RLSのテスト方法にあり、アプリ全体でgrantとポリシーがどうなるかはLovableアプリのセキュリティチェックリストにあります。

© 2026 Denys Zaichenko. 元の記事: https://madsalt.tech/ja/notes/supabase-42501-permission-denied/