fix(admin): retry GoTrue admin reads on transient empty-body responses (bulk-load robustness)

This commit is contained in:
Gerhard Scheikl
2026-05-31 15:35:33 +02:00
parent d317e8c758
commit 17fe642168
4 changed files with 165 additions and 14 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
import { notFound } from 'next/navigation';
import Link from 'next/link';
import { getSupabaseAdmin } from '@/lib/supabase/admin';
import { withAdminRetry } from '@/lib/admin/retry';
import { createSupabaseServerClient } from '@/lib/supabase/server';
import { isUuid } from '@/lib/admin/validators';
import { formatBytes, formatDate } from '@/lib/format';
@@ -41,8 +42,8 @@ export default async function AdminUserDetailPage({
data: { user: currentUser },
} = await supabase.auth.getUser();
const { data: userRes, error } = await admin.auth.admin.getUserById(
params.id,
const { data: userRes, error } = await withAdminRetry(() =>
admin.auth.admin.getUserById(params.id),
);
if (error || !userRes.user) notFound();
const u = userRes.user;
+12 -5
View File
@@ -1,6 +1,7 @@
import { type NextRequest } from 'next/server';
import { requireAdminApi } from '@/lib/auth/admin-guard';
import { getSupabaseAdmin } from '@/lib/supabase/admin';
import { withAdminRetry } from '@/lib/admin/retry';
import { logAdminAction } from '@/lib/auth/audit';
import { isUuid } from '@/lib/admin/validators';
import { jsonNoStore } from '@/lib/admin/response';
@@ -33,8 +34,12 @@ export async function GET(
const admin = getSupabaseAdmin();
const { data: userRes, error: userErr } =
await admin.auth.admin.getUserById(id);
// Retry transient empty-body GoTrue responses so a burst-induced flake isn't
// misreported as a 404 for a user that actually exists. A genuine not-found
// (non-transient) still falls through to the clean 404 below.
const { data: userRes, error: userErr } = await withAdminRetry(() =>
admin.auth.admin.getUserById(id),
);
if (userErr || !userRes.user) {
return jsonNoStore({ error: 'user not found' }, { status: 404 });
}
@@ -103,9 +108,11 @@ export async function DELETE(
// Confirm the user exists up front. GoTrue replies with an empty body when
// deleting a non-existent user, which supabase-js surfaces as an opaque
// JSON-parse error (no status / "not found" text); a positive existence
// check lets us return a clean 404 instead of a misleading 500.
const { data: existing, error: lookupErr } =
await admin.auth.admin.getUserById(id);
// check lets us return a clean 404 instead of a misleading 500. Retry the
// lookup so a transient empty body under load isn't mistaken for not-found.
const { data: existing, error: lookupErr } = await withAdminRetry(() =>
admin.auth.admin.getUserById(id),
);
if (lookupErr || !existing.user) {
return jsonNoStore({ error: 'user not found' }, { status: 404 });
}