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

Server组件动态路由中async-await调用Prisma报错的修复咨询

问题描述

点击「Add New」按钮时触发以下错误:

PrismaClientKnownRequestError: Invalid prisma.billboard.findUnique() invocation:

Inconsistent column data: Malformed ObjectID: provided hex string representation must be exactly 12 bytes, instead got: "new", length 3.

at async BillboardPage (billboards/[billboardId]/page.tsx:14:23)
digest: "1047868513"

报错页面代码(billboards/[billboardId]/page.tsx)

const BillboardPage = async ({
  params
}: {
  params: { billboardId: string }
}) => {
  console.log("Billboard ID:", params.billboardId);
  const billboard = await prismadb.billboard.findUnique({
    where: {
      id: params.billboardId
    }
  });

  return ( 
    <div className="flex-col">

      <div className="flex-1 space-y-4 p-8 pt-6">
        <BillboardForm initialData={billboard} />
      </div>
    </div>
  );
};

export default BillboardPage;

路由触发代码

export const BillboardClient = () => {
    const router = useRouter();
    const params = useParams();
   return (
        <>
        <div className="flex items-center justify-between">
          <Heading 
          title="Billboards (0)"
          description="Manage Billboards for your store"
          />
          <Button  onClick={() => router.push(`/${params.storeId}/billboards/new`)}>
            <Plus className="mr-w h-4 w-4"/>
            Add New
          </Button>
        </div>
        <Separator />
        </>
    )
}

问题原因

动态路由billboards/[billboardId]会匹配所有billboards/xxx格式的路径,包括跳转的billboards/new。这导致BillboardPage组件把字符串"new"当作billboardId传入Prisma查询,但Prisma要求id字段必须是12字节的ObjectID格式,直接用"new"查询触发了格式错误。


修复方案

方案1:拆分路由,新增单独的新建页面

在billboards目录下创建new/page.tsx,专门处理新建逻辑:

// billboards/new/page.tsx
const NewBillboardPage = () => {
  return (
    <div className="flex-col">
      <div className="flex-1 space-y-4 p-8 pt-6">
        <BillboardForm initialData={null} /> {/* 传null表示新建模式 */}
      </div>
    </div>
  );
};

export default NewBillboardPage;

同时修改原BillboardPage,增加ID格式校验:

// billboards/[billboardId]/page.tsx
const BillboardPage = async ({
  params
}: {
  params: { billboardId: string }
}) => {
  // 校验ObjectID格式(24位十六进制字符串)
  if (!/^[0-9a-fA-F]{24}$/.test(params.billboardId)) {
    return <div>无效的广告牌ID</div>;
  }

  const billboard = await prismadb.billboard.findUnique({
    where: {
      id: params.billboardId
    }
  });

  if (!billboard) {
    return <div>未找到该广告牌</div>;
  }

  return ( 
    <div className="flex-col">
      <div className="flex-1 space-y-4 p-8 pt-6">
        <BillboardForm initialData={billboard} />
      </div>
    </div>
  );
};

export default BillboardPage;

方案2:在现有页面中区分编辑/新建模式

如果不想新增页面,可以在BillboardPage中判断参数是否为"new",切换逻辑:

const BillboardPage = async ({
  params
}: {
  params: { billboardId: string }
}) => {
  let billboard = null;
  const isNew = params.billboardId === "new";

  if (!isNew) {
    // 非新建模式,校验ID格式并查询数据
    if (!/^[0-9a-fA-F]{24}$/.test(params.billboardId)) {
      return <div>无效的广告牌ID</div>;
    }
    billboard = await prismadb.billboard.findUnique({
      where: {
        id: params.billboardId
      }
    });
    if (!billboard) {
      return <div>未找到该广告牌</div>;
    }
  }

  return ( 
    <div className="flex-col">
      <div className="flex-1 space-y-4 p-8 pt-6">
        <BillboardForm initialData={billboard} isNew={isNew} /> {/* 传递新建状态给表单 */}
      </div>
    </div>
  );
};

export default BillboardPage;

注意需要同步修改BillboardForm组件,使其能处理initialData为null的情况,区分新增和编辑逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:32:42