typescriptnext.jsnextjs-dynamic-routing

How to fix 'params is not a valid type' error in Next.js API route with TypeScript?


I am trying to deploy this project and i keep getting an error message:

app/api/invoice/markAsPaid/[invoiceId]/route.ts
Type error: Route "app/api/invoice/markAsPaid/[invoiceId]/route.ts" has an invalid "PATCH" export:
Type "{ params: { invoiceId: string; }; }" is not a valid type for the function's second argument

this is the code

"use server";

import { NextRequest, NextResponse } from "next/server";
import prisma from "@/app/utils/db";
import { requireUser } from "@/app/utils/hooks";

// PATCH function to mark invoice as PAID
export async function PATCH(
  request: NextRequest,
  context: { params: { invoiceId: string } } // Typing context correctly
) {
  // @ts-ignore: Ignore TypeScript error for params typing
  const { invoiceId } = context.params;  // Get the invoiceId from the context params

  try {
    const session = await requireUser();
    if (!session?.user?.id) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Update the invoice status to "PAID"
    const updatedInvoice = await prisma.invoice.update({
      where: { id: invoiceId },
      data: { status: "PAID" },
    });

    return NextResponse.json({ success: true, invoice: updatedInvoice });
  } catch (error: any) {
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}

Its working fine in development and there seems to be no type error however i have disable most of the eslint rules as much as i could but still it seems the error is there while deploying on vercel


Solution

  • Next.js v15 made a change to the params context property, requiring it to be a Promise.

    Async Request APIs (Breaking change)

    Previously synchronous Dynamic APIs that rely on runtime information are now asynchronous:

    • params in layout.js, page.js, route.js, default.js, opengraph-image, twitter-image, icon, and apple-icon.

    You'll need something like this now...

    type Params = Promise<{ invoiceId: string }>;
    
    export async function PATCH(
      request: Request,
      { params }: { params: Params }
    ) {
      const { invoiceId } = await params;
      // ...
    

    See also the updated instructions for Route Handlers - Dynamic Route Segments