fix(admin): return 404 (not 500) when deleting an already-removed user

GoTrue returns an empty body for a missing-user delete, surfacing as an
opaque JSON-parse error; pre-check existence via getUserById for a clean 404.
This commit is contained in:
Gerhard Scheikl
2026-05-31 13:23:43 +02:00
parent 535b2ef202
commit dd0ff39890
+10 -5
View File
@@ -100,16 +100,21 @@ export async function DELETE(
const admin = getSupabaseAdmin(); const admin = getSupabaseAdmin();
// 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);
if (lookupErr || !existing.user) {
return jsonNoStore({ error: 'user not found' }, { status: 404 });
}
// Delete the AUTH USER first. Only if that succeeds do we remove the tunnel // Delete the AUTH USER first. Only if that succeeds do we remove the tunnel
// row, so a mid-failure never leaves an orphaned auth user with a dangling // row, so a mid-failure never leaves an orphaned auth user with a dangling
// tunnel (or half-deletes the tunnel of an already-gone user). // tunnel (or half-deletes the tunnel of an already-gone user).
const { error: delErr } = await admin.auth.admin.deleteUser(id); const { error: delErr } = await admin.auth.admin.deleteUser(id);
if (delErr) { if (delErr) {
const httpStatus = (delErr as { status?: number }).status;
const message = (delErr.message ?? '').toLowerCase();
if (httpStatus === 404 || message.includes('not found')) {
return jsonNoStore({ error: 'user not found' }, { status: 404 });
}
console.error('admin user.delete: deleteUser failed', delErr); console.error('admin user.delete: deleteUser failed', delErr);
return jsonNoStore({ error: 'internal error' }, { status: 500 }); return jsonNoStore({ error: 'internal error' }, { status: 500 });
} }