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

Node.js+Prisma获取表单时出现ObjectID无效的PrismaClientKnownRequestError

解决PrismaClientKnownRequestError: Malformed ObjectID(传入无效ID导致)

问题根源

  1. 前端异步依赖问题:useGetBooking是异步请求,初始状态下booking为undefined,此时formId = booking?.form?.id结果为undefined。加上非空断言formId!后,模板字符串会将undefined转为字符串"undefined",导致请求URL变为/users/getForm/undefined。
  2. 后端校验漏洞:当前端传入字符串"undefined"时,后端原校验逻辑if (!id || id.length === 0)无法拦截("undefined"是真值且长度不为0),直接进入Prisma查询环节。而Prisma要求MongoDB ObjectID必须是12字节的十六进制字符串,"undefined"不符合格式,触发P2023错误。

解决方案

前端修复:控制请求时机

给useGetForm添加enabled选项,仅当formId有效时才发起请求,同时移除非空断言避免强制传递无效值:

const { id } = useParams<{ id: string }>()
const { data: booking } = useGetBooking(id!)

const formId = booking?.form?.id
// 仅当formId存在时才执行查询
const { data: form } = useGetForm(formId, { enabled: !!formId })

// 同步修改useGetForm,允许id为可选值并在校验后发起请求
export function useGetForm(id?: string) {
  return useQuery({
    queryKey: ['form', id],
    queryFn: () => {
      if (!id) throw new Error('Form ID 必填')
      return getForm({ id })
    },
    enabled: !!id,
  })
}

后端修复:加强ID格式校验

除了判断是否为空,新增ObjectID格式校验(12字节十六进制字符串),拦截无效ID:

import { ObjectId } from 'mongodb'; // 或使用Prisma.ObjectId

export const getForm = async (req: Request, res: Response) => {
  try {
    const { id } = req.params; 
    console.log('form id->', id); 

    // 校验ID是否为空且符合ObjectID格式
    if (!id || !ObjectId.isValid(id)) {
      console.log('id inválido');
      return res.status(400).json({ message: "ID inválido." });
    }

    const form = await prisma.form.findUnique({
      where: { id },
      include: { form_fields: true },
    });

    if (!form) {
      return res.status(404).json({ message: "Formulário não encontrado." });
    }

    return res.status(200).json(form);
  } catch (error) {
    console.error(error);
    return res.status(500).json({ message: "Erro ao buscar o formulário." });
  }
};

额外优化:前端请求前校验

在getForm函数中添加ID格式校验,提前拦截无效请求:

async function getForm({ id }: { id: string }) {
  if (!id || !/^[0-9a-fA-F]{24}$/.test(id)) {
    throw new Error('Form ID格式无效')
  }
  try {
    const response = await privateRequest.get(`/users/getForm/${id}`)
    return response.data
  } catch (error) {
    if (isAxiosError(error)) {
      throw new Error(error.response?.data.message)
    } else {
      throw new Error('未知错误')
    }
  }
}

内容的提问来源于stack exchange,提问作者Cláudio Vitor Dantas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:37:04