From b5ee699a281060e1c290306c2e5ef3e42f482a11 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 28 Sep 2026 06:05:51 +0000 Subject: [PATCH] Add error handling for database failures in signup/login/profile None of the database calls in these three places were wrapped in try/catch, so any database hiccup (disk issue, lock contention, etc.) surfaced as an unhandled 500 with a useless generic message and no server-side log to explain why. Found this while testing every page's redirects end to end: a broken test setup on my end (an old server process left running against a deleted database file) produced exactly this failure mode, which would look identical to a real intermittent outage to an end user. Now: signup and profile-update return a clear "try again in a moment" message with the real error logged server-side; login logs the real error but still shows the existing generic "incorrect email or password" message to the client (matches current behavior, avoids leaking account existence). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01VL5YUEf2B9LG4xdVUQwcSg --- src/app/api/profile/route.ts | 20 ++++++++++++++------ src/app/api/signup/route.ts | 32 ++++++++++++++++++++------------ src/lib/auth.ts | 23 +++++++++++++++-------- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/app/api/profile/route.ts b/src/app/api/profile/route.ts index 08c87e9..fb13791 100644 --- a/src/app/api/profile/route.ts +++ b/src/app/api/profile/route.ts @@ -28,11 +28,19 @@ export async function PATCH(request: Request) { return NextResponse.json({ error: message }, { status: 400 }); } - const user = await prisma.user.update({ - where: { id: session.user.id }, - data: parsed.data, - select: { id: true, name: true, email: true, age: true, bio: true }, - }); + try { + const user = await prisma.user.update({ + where: { id: session.user.id }, + data: parsed.data, + select: { id: true, name: true, email: true, age: true, bio: true }, + }); - return NextResponse.json({ user }); + return NextResponse.json({ user }); + } catch (err) { + console.error("profile update failed:", err); + return NextResponse.json( + { error: "We couldn't save your changes right now. Please try again in a moment." }, + { status: 503 }, + ); + } } diff --git a/src/app/api/signup/route.ts b/src/app/api/signup/route.ts index 64c6b34..a7a41a2 100644 --- a/src/app/api/signup/route.ts +++ b/src/app/api/signup/route.ts @@ -26,17 +26,25 @@ export async function POST(request: Request) { const { name, email, password, age } = parsed.data; - const existing = await prisma.user.findUnique({ where: { email } }); - if (existing) { - return NextResponse.json({ error: "An account with that email already exists" }, { status: 409 }); + try { + const existing = await prisma.user.findUnique({ where: { email } }); + if (existing) { + return NextResponse.json({ error: "An account with that email already exists" }, { status: 409 }); + } + + const passwordHash = await bcrypt.hash(password, 12); + + const user = await prisma.user.create({ + data: { name, email, age, passwordHash }, + select: { id: true, email: true, name: true }, + }); + + return NextResponse.json({ user }, { status: 201 }); + } catch (err) { + console.error("signup failed:", err); + return NextResponse.json( + { error: "We couldn't create your account right now. Please try again in a moment." }, + { status: 503 }, + ); } - - const passwordHash = await bcrypt.hash(password, 12); - - const user = await prisma.user.create({ - data: { name, email, age, passwordHash }, - select: { id: true, email: true, name: true }, - }); - - return NextResponse.json({ user }, { status: 201 }); } diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 38e2642..bd85363 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -18,17 +18,24 @@ export const authOptions: AuthOptions = { async authorize(credentials) { if (!credentials?.email || !credentials?.password) return null; - await ensureDb(); + try { + await ensureDb(); - const user = await prisma.user.findUnique({ - where: { email: credentials.email.toLowerCase() }, - }); - if (!user) return null; + const user = await prisma.user.findUnique({ + where: { email: credentials.email.toLowerCase() }, + }); + if (!user) return null; - const valid = await bcrypt.compare(credentials.password, user.passwordHash); - if (!valid) return null; + const valid = await bcrypt.compare(credentials.password, user.passwordHash); + if (!valid) return null; - return { id: user.id, email: user.email, name: user.name }; + return { id: user.id, email: user.email, name: user.name }; + } catch (err) { + // Logged so a database hiccup is visible server-side, even though + // the client only ever sees a generic "incorrect email or password". + console.error("login authorize() failed:", err); + return null; + } }, }), ],