You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js POST请求500内部服务器错误排查求助

Next.js API路由500错误排查与修复

问题核心原因

  1. 前端未提交authUserId:表单未携带Supabase用户认证ID,后端解构时authUserId为undefined,导致Supabase数据库操作因缺少查询条件报错。
  2. Update操作无返回数据:Supabase的update方法默认不返回更新记录,需添加.select()才能获取有效结果,否则会误判为无用户存在而执行insert,若email已存在则触发唯一约束错误。
  3. 未处理空值校验:后端未提前校验authUserId等必填字段,直接执行数据库操作引发报错。

修复步骤

1. 前端补充用户认证ID提交

修改/app/user-profile/page.tsx,获取当前登录用户ID并加入提交数据:

'use client';

import React, { useEffect, useState } from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import toast from 'react-hot-toast';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import DeveloperButtons from '@/app/components/DeveloperButtons';
import { supabase } from '@/app/utils/client';

const profileSchema = z.object({
    name: z.string().min(1, { message: 'Name is required' }),
    email: z.string().email({ message: 'Invalid email format' }),
    age: z.coerce
        .number()
        .int()
        .min(0, { message: 'Invalid age' })
        .max(100, { message: 'Invalid age' }),
    gender: z.string().min(1, { message: 'Gender is required' }),
    occupation: z.string(),
    hourly_rate: z.coerce
        .number()
        .int()
        .min(0, { message: 'Invalid hourly rate' }),
});

type ProfileFormData = z.infer<typeof profileSchema>;

const UserProfile = () => {
    const [authUserId, setAuthUserId] = useState<string | null>(null);
    const {
        register,
        handleSubmit,
        reset,
        formState: { errors },
    } = useForm<ProfileFormData>({
        resolver: zodResolver(profileSchema),
    });

    // 获取当前登录用户ID
    useEffect(() => {
        const getCurrentUser = async () => {
            const { data: { user } } = await supabase.auth.getUser();
            if (user) {
                setAuthUserId(user.id);
            } else {
                toast.error('请先登录');
            }
        };
        getCurrentUser();
    }, []);

    const onSubmit: SubmitHandler<ProfileFormData> = async (data) => {
        if (!authUserId) {
            toast.error('用户未登录');
            return;
        }
        const response = await fetch('/api/user-profile/', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ ...data, authUserId }),
        });

        const result = await response.json();
        if (response.ok) {
            toast.success('Profile updated successfully!');
        } else {
            toast.error(result.error || '更新失败');
        }
    };

    // 原页面渲染代码保持不变
    return (
        <div className='container mx-auto p-4'>
            <DeveloperButtons />
            <form
                onSubmit={handleSubmit(onSubmit)}
                className='form-control w-full max-w-xs pt-8'
            >
                {/* 表单输入项代码保持不变 */}
            </form>
        </div>
    );
};

export default UserProfile;

2. 后端API逻辑优化

修改/app/api/user-profile/route.ts,添加字段校验、优化Supabase操作:

import { NextRequest, NextResponse } from 'next/server';
import { supabase } from '@/app/utils/client';
import { UserProfileUpdateData } from '@/app/types/userProfile';

export async function POST(req: NextRequest) {
    try {
        const {
            authUserId,
            name,
            email,
            age,
            gender,
            occupation,
            hourly_rate,
        }: UserProfileUpdateData = await req.json();

        // 校验必填字段
        if (!authUserId || !email) {
            return NextResponse.json(
                { error: 'authUserId和email为必填项' },
                { status: 400 }
            );
        }

        // 添加.select()获取更新后的记录
        const { data: updateData, error: updateError } = await supabase
            .from('users')
            .update({ name, email, age, gender, occupation, hourly_rate })
            .eq('auth_user_id', authUserId)
            .select();

        if (updateError) throw updateError;

        // 无更新记录则执行插入
        if (!updateData || updateData.length === 0) {
            const { error: insertError } = await supabase.from('users').insert([
                {
                    auth_user_id: authUserId,
                    name,
                    email,
                    age,
                    gender,
                    occupation,
                    hourly_rate,
                    number_of_active_projects: 0,
                    number_of_completed_projects: 0,
                },
            ]);

            if (insertError) throw insertError;
            return NextResponse.json({ message: '用户资料创建成功' }, { status: 201 });
        }

        return NextResponse.json({ message: '用户资料更新成功' }, { status: 200 });
    } catch (error: any) {
        return NextResponse.json(
            { error: error.message || '服务器内部错误' },
            { status: 500 }
        );
    }
}

3. 额外检查项

  • 确认utils/client.ts中的Supabase客户端配置正确,已设置NEXT_PUBLIC_SUPABASE_URL和NEXT_PUBLIC_SUPABASE_ANON_KEY环境变量。
  • 检查Supabase控制台「权限」面板,确保anon用户拥有users表的insert和update权限。
  • 查看Supabase控制台「日志」面板,获取具体数据库错误信息辅助排查。

内容的提问来源于stack exchange,提问作者TheSnowmann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 02:53:12