エラーの概要
Supabaseの500エラーは、Supabaseサーバー側で予期しない内部エラーが発生したことを示します。クライアント側のリクエストは正しくても、PostgreSQLの実行エラー・Functionsの例外処理漏れ・インフラストラクチャの一時的な問題など、複数の原因が考えられます。このエラーが発生した場合は、サーバーログを確認して具体的な原因を特定する必要があります。
実際のエラーメッセージ例
JavaScriptクライアント(supabase-js)での出力例:
{
"error": {
"message": "Internal Server Error",
"status": 500
},
"statusCode": 500
}
Supabase REST APIの直接呼び出し時の例:
{
"code": "PGRST500",
"message": "relation \"public.users\" does not exist",
"details": null,
"hint": null
}
ブラウザコンソールでの出力例:
Error: Internal Server Error
at async Session.from (auth.ts:456:23)
よくある原因と解決手順
原因1:PostgreSQLのクエリが構文エラーまたは実行時エラーになっている
Supabaseに送信するSQLクエリに構文エラーがあったり、存在しないテーブル・カラムを参照していたりする場合、500エラーが発生します。特にRLS(Row Level Security)のポリシー内で不正なテーブル参照をしていると、クエリ実行時に内部エラーとなります。
Before(エラーが起きるコード):
const { data, error } = await supabase
.from('users')
.select('id, name, invalid_column')
.eq('status', 'active');
if (error) {
console.log('Error:', error.message);
}
After(修正後):
const { data, error } = await supabase
.from('users')
.select('id, name, email')
.eq('status', 'active');
if (error) {
console.log('Error:', error.message);
}
または、実際にカラムが存在することを事前確認し、テーブル定義を正しくする必要があります。Supabase Dashboardの「SQL Editor」でクエリを事前テストすることをお勧めします。
Before(エラーが起きるコード):
CREATE POLICY "users_select_policy" ON public.users
FOR SELECT USING (
user_id = auth.uid() AND deleted_at IS NULL
);
After(修正後):
CREATE POLICY "users_select_policy" ON public.users
FOR SELECT USING (
id = auth.uid()
);
原因2:Supabase Functionsのコードで未処理の例外が発生している
Functionsで実装したエッジファンクション(Supabaseの別環境で実行される関数)が予期しない例外をスローしているか、try-catchで捕捉できていないエラーが発生している場合、500エラーが返されます。
Before(エラーが起きるコード):
// supabase/functions/process-payment/index.ts
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
serve(async (req) => {
const { amount } = await req.json();
const result = amount / 0; // 明らかなエラーではないが、後続処理で例外が発生
return new Response(JSON.stringify({ result }));
});
After(修正後):
// supabase/functions/process-payment/index.ts
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
serve(async (req) => {
try {
const { amount } = await req.json();
if (!amount || amount <= 0) {
return new Response(
JSON.stringify({ error: "Invalid amount" }),
{ status: 400 }
);
}
const result = amount * 0.1;
return new Response(JSON.stringify({ result }), { status: 200 });
} catch (error) {
console.error("Function error:", error);
return new Response(
JSON.stringify({ error: "Internal server error" }),
{ status: 500 }
);
}
});
原因3:Supabaseインフラで一時的な障害が起きている
Subaseのバックエンドサービス(PostgreSQL、Auth、Realtimeなどのインフラストラクチャレイヤーまたはデータセンター)で一時的な障害が発生していることもあります。この場合、ユーザー側では対処できず、Supabaseサービスの復旧を待つ必要があります。
確認方法:
Supabase公式ステータスページ(status.supabase.com)にアクセスして、現在のサービス状態を確認します。
Before(エラーが起きるコード):
const { data, error } = await supabase
.from('posts')
.select('*');
if (error?.status === 500) {
// すぐに再度呼び出し
const { data: retryData } = await supabase
.from('posts')
.select('*');
}
After(修正後):
async function fetchWithRetry(maxRetries = 3, delay = 1000) {
for (let i = 0; i < maxRetries; i++) {
try {
const { data, error } = await supabase
.from('posts')
.select('*');
if (!error) {
return data;
}
if (error.status === 500) {
if (i < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
continue;
}
}
throw error;
} catch (err) {
console.error(`Attempt ${i + 1} failed:`, err);
}
}
}
const data = await fetchWithRetry();
ツール固有の注意点
Supabase Dashboardのログ確認方法
Supabase Dashboardの「Logs」セクションは、500エラーの具体的な原因を特定するために不可欠です。
- SQL Logs:
Home > Logs > PostgreSQLで、実行されたクエリと詳細なエラーメッセージを確認できます。 - Function Logs:
Edge Functionsのログから、デプロイされたFunctionのコンソール出力とエラースタックトレースを確認できます。 - Auth Logs:認証絡みのエラーは
Authentication > Logsで確認します。
RLS(Row Level Security)ポリシーのデバッグ
RLSポリシー内でのエラーは特定が難しいため、デバッグモード有効化が推奨されます。
Before(エラーが起きるコード):
CREATE POLICY "check_user" ON public.posts
FOR SELECT USING (user_id = auth.uid());
After(修正後):
-- 開発環境でのみRLSを一時的に無効化して、実際のテーブルアクセス確認
ALTER TABLE public.posts DISABLE ROW LEVEL SECURITY;
-- その後、ポリシーをテストして有効化
ALTER TABLE public.posts ENABLE ROW LEVEL SECURITY;
マルチテナント構成での500エラー
複数のスキーマやテーブルを使用する場合、権限設定が不十分だと500エラーが発生します。
Before(エラーが起きるコード):
CREATE TABLE public.users (id BIGINT PRIMARY KEY);
-- 権限付与なし
After(修正後):
CREATE TABLE public.users (id BIGINT PRIMARY KEY);
GRANT SELECT ON public.users TO authenticated;
GRANT INSERT, UPDATE ON public.users TO authenticated;
GRANT SELECT ON public.users TO anon;
それでも解決しない場合
ステップ1:Supabaseステータスページを確認
# ブラウザで以下にアクセス
https://status.supabase.com
現在のインシデント情報を確認します。障害が報告されている場合は、復旧を待ちます。
ステップ2:詳細ログを確認
Supabase Dashboard > Logs セクションで以下を順番に確認します:
- PostgreSQL Logs(
SELECT * FROM ...の実行ログ) - Function Logs(デプロイされたFunctionの標準出力・エラー出力)
- Auth Logs(認証関連のエラー)
ステップ3:cURLコマンドで直接APIをテスト
# Supabase REST APIを直接呼び出して、エラーメッセージの詳細を取得
curl -X GET "https://<your-project>.supabase.co/rest/v1/users?select=*" \
-H "apikey: <your-public-key>" \
-H "Authorization: Bearer <your-token>"
エラーレスポンスに含まれる code と message フィールドから、より詳細な原因を特定できます。
ステップ4:ローカルでの再現テスト
# supabase-cliをインストール(未インストールの場合)
npm install -g supabase
# ローカルエミュレーターを起動
supabase start
# ローカル環境でクエリをテスト
curl -X GET "http://localhost:54321/rest/v1/users" \
-H "apikey: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
ステップ5:公式サポートへの問い合わせ
Supabase公式ドキュメント(https://supabase.com/docs)または、GitHub Discussions(https://github.com/supabase/supabase/discussions)で同様の問題事例を検索します。解決しない場合は、以下の情報を添付して問い合わせます:
- Project ID
- 発生時刻(UTC)
- エラーメッセージの全文
- 実行したクエリまたはFunction名
免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。