next.js

Next.js 15.2.3 server api get gives 'route.ts has an invalid GET export: Type "{ params?: { monitorId?: string | undefined; } | undefined; }" is not'


I have a Next.js 15.2.3 server api route that takes in a monitorId and gives back a result in the database.

The Next.js 15.2.3 server api route path is app/(private)/monitors/[monitorId]/api-get-monitor/route.ts.

// app/(private)/monitors/[monitorId]/api-get-monitor/route.ts

import { NextRequest, NextResponse } from "next/server";
import { sql } from "@/app/lib/db";
import { loginIsRequiredServer } from "@/app/lib/loginIsRequiredServer";
import { getServerSession } from "next-auth";
import { authConfig } from "@/app/lib/auth";

// Use the built-in RequestContext type
export async function GET(request: NextRequest, context: { params?: { monitorId?: string } }) {
  // Ensure params exist
  if (!context.params?.monitorId) {
    return NextResponse.json({ message: "Missing monitor ID" }, { status: 400 });
  }

  const { monitorId } = context.params;

  console.error(`api-get-monitor · Get Monitor: ${monitorId}`);

  // Session check
  await loginIsRequiredServer();
  const session = await getServerSession(authConfig);
  if (!session) {
    return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
  }

  try {
    // Query the database for monitor details using the monitorId
    const res = await sql(
      `SELECT monitor_id, title, what_to_monitor, url_to_monitor, escalation_email_on, 
      escalation_email_to, check_frequency, last_checked_timestamp, is_offline, offline_datetime
      FROM u_monitors_index WHERE monitor_id = $1`,
      [monitorId]
    );

    if (res.rows.length === 0) {
      return NextResponse.json({ message: "Monitor not found" }, { status: 404 });
    }

    return NextResponse.json({ data: res.rows[0] });
  } catch (error) {
    console.error("get-monitor · Error getting:", error);
    return NextResponse.json({ message: "Error getting monitor" }, { status: 500 });
  }
}

This works locally but when I deploy it to Google Cloud Run I get the following error

   Linting and checking validity of types ...
Failed to compile.
app/(private)/monitors/[monitorId]/api-get-monitor/route.ts
Type error: Route "app/(private)/monitors/[monitorId]/api-get-monitor/route.ts" has an invalid "GET" export:
  Type "{ params?: { monitorId?: string | undefined; } | undefined; }" is not a valid type for the function's second argument.
    Expected "Promise<any>", got "{ monitorId?: string | undefined; } | undefined".
      Expected "Promise<any>", got "undefined".
Next.js build worker exited with code: 1 and signal: null

Is not params is just an object passed by Next.js, not an async operation? I do not understand the error here.


Solution

  • You're getting that error during your production build because from NextJS 15, params is now a promise and not a synchronous object as they were in the versions preceding NextJS 15. All you have to do is adjust your type for your params to be a promise object.

    export async function GET(request: NextRequest, context: { params: Promise<{ monitorId: string }> }) {
    
      const monitorId = (await context.params).monitorId;
    
      // Ensure params exist
      if (!monitorId) {
        return NextResponse.json({ message: "Missing monitor ID" }, { status: 400 });
      }
    
      console.error(`api-get-monitor · Get Monitor: ${monitorId}`);
    
      // Session check
      await loginIsRequiredServer();
      const session = await getServerSession(authConfig);
      if (!session) {
        return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
      }
    
      try {
        // Query the database for monitor details using the monitorId
        const res = await sql(
          `SELECT monitor_id, title, what_to_monitor, url_to_monitor, escalation_email_on, 
          escalation_email_to, check_frequency, last_checked_timestamp, is_offline, offline_datetime
          FROM u_monitors_index WHERE monitor_id = $1`,
          [monitorId]
        );
    
        if (res.rows.length === 0) {
          return NextResponse.json({ message: "Monitor not found" }, { status: 404 });
        }
    
        return NextResponse.json({ data: res.rows[0] });
      } catch (error) {
        console.error("get-monitor · Error getting:", error);
        return NextResponse.json({ message: "Error getting monitor" }, { status: 500 });
      }
    }
    

    Here is a reference to the docs: https://nextjs.org/docs/app/api-reference/file-conventions/route#context-optional