Free tool · Next.js 16 · App Router

Paste the Next.js error.
Get the fix.

20 App Router errors that AI agents keep causing, each reproduced on Next.js 16. You get what it means, the fix and a prompt to hand back to Cursor or Claude Code.

next-error-fixer — runs in your browser, nothing is sent

try:

› 20 errors indexed. Matching runs locally as you type.

  • 20 errors
  • 5 only fail at next build
  • reproduced on Next.js 16.4.3 · React 19.3
  • updated

01The usual suspects

Your agent learned Next.js 13. You're on 16.

Server Components by default, async params, cacheComponents, proxy.ts: most examples agents learned from predate all of it. These 10 come up again and again:

  1. 01useState / useEffect in a Server ComponentThe agent added state or an effect to a page.tsx or layout.tsxFix: move the hook into a "use client" component →
  2. 02Event handlers cannot be passed to Client Component propsonClick added to a <button> directly in page.tsxFix: put the onClick inside a Client Component →
  3. 03"use client" must be placed before other expressionsAn agent inserted imports above "use client"Fix: move "use client" to line 1 →
  4. 04Module not found: Can't resolve 'fs'fs or path used inside a "use client" fileFix: keep Node APIs in server code →
  5. 05useSearchParams() should be wrapped in a suspense boundaryA login or search page reads ?error= or ?q= with useSearchParamsFix: wrap the component in <Suspense> →
  6. 06Next.js encountered runtime / uncached data during prerendering (cacheComponents)const session = await auth() at the top of a pageFix: <Suspense> around it, or export const instant = false →
  7. 07params.slug is undefined (params is a Promise)The page is typed { params: { slug: string } } (the old shape), so TypeScript doesn't catch itFix: const { slug } = await params →
  8. 08Hydration failed: server HTML didn't match the clientnew Date(), Date.now() or Math.random() in renderFix: no Date.now / Math.random / window during render →
  9. 09The "middleware" file convention is deprecatedAn agent added auth or redirects in middleware.tsFix: rename middleware.ts to proxy.ts →
  10. 10npm ci: package.json and package-lock.json are not in syncAn agent edited the next, react or eslint-config-next version in package.json, or ran npm install next@latest, while fixing something elseFix: pin next, commit the lockfile, use npm ci →
  11. tell your agent
    • Next.js 16, App Router
    • Server Components by default
    • "use client" only for interactivity
    • await params and searchParams
    • proxy.ts, not middleware.ts
    • Run next build before you finish
    Generate an AGENTS.md with these rules →

02Every error, explained

The full list.

01build erroragents cause this

useState / useEffect in a Server Component

Error: You're importing a module that depends on `useState` into a React Server Component module. This API is only available in Client Components. To fix, mark the file (or its parent) with the `"use client"` directive.

Every file in the App Router is a Server Component unless it (or a file that imports it) starts with "use client". Hooks like useState, useEffect, useRef and createContext only work in Client Components.

usually because

  • The agent added state or an effect to a page.tsx or layout.tsx
  • A component from a tutorial written for the Pages Router
  • A context provider placed straight into layout.tsx

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Puts "use client" only on the small leaf that needs state or effects.

fix

  1. 1.Move the interactive part into its own file that starts with "use client"
  2. 2.Keep page.tsx a Server Component and render the new component from it
  3. 3.Don't mark the whole page "use client" just to silence the error: you lose server data fetching and metadata
src/components/counter.tsx
"use client";

import { useState } from "react";

export function Counter() {
  const [n, setN] = useState(0);
  return <button onClick={() => setN(n + 1)}>{n}</button>;
}
prompt for your agent

Next.js build fails because a Server Component imports a client-only hook. Find the component that uses the hook, move only the interactive part into a new file that starts with "use client", and keep page.tsx and layout.tsx as Server Components. Don't add "use client" to the page itself.

02next build (prerender)agents cause this

Event handlers cannot be passed to Client Component props

Error occurred prerendering page "/pricing".
Error: Event handlers cannot be passed to Client Component props.
  {onClick: function onClick, children: ...}
            ^^^^^^^^^^^^^^^^
If you need interactivity, consider converting part of this to a Client Component.

A Server Component rendered an element with onClick, onChange or any prop starting with "on" set to a function. Functions can't be sent from the server to the browser, so rendering stops.

usually because

  • onClick added to a <button> directly in page.tsx
  • A Server Component passes onSomething={() => …} to a Client Component
  • It often only shows up at next build, when the page is prerendered

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Keeps pages as Server Components and moves onClick into a small client leaf.

fix

  1. 1.Move the button (and its handler) into a "use client" component
  2. 2.Or keep it on the server: use a <form action={serverAction}> instead of onClick
  3. 3.If the child is already a Client Component, define the handler inside it instead of passing it down
prompt for your agent

next build fails with "Event handlers cannot be passed to Client Component props". Find the Server Component that sets an on* prop to a function, and either move that element into a "use client" component or replace the handler with a Server Action used as a form action. Show me the diff.

03next build (prerender)

Functions cannot be passed directly to Client Components

Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.

Same rule as above for props not named on*: a Server Component passed a plain function (a formatter, a callback, a render prop) to a Client Component.

usually because

  • formatPrice={(n) => …} passed from a page to a client chart or table
  • A render prop like renderItem from a Server Component
  • Passing a function reference when you meant to pass its result

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Only serializable props cross to client components, and no functions other than Server Actions.

fix

  1. 1.Pass data, not functions: call the function on the server and pass the result
  2. 2.Or import the helper directly inside the Client Component
  3. 3.If it must run on the server when the client calls it, make it a Server Action in a "use server" file
prompt for your agent

A Server Component passes a function prop to a Client Component and Next.js refuses to serialize it. Find it, then either pass the computed value instead, import the helper inside the client file, or turn it into a Server Action if it needs server access.

04next build (prerender)

Only plain objects can be passed to Client Components

Error: Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported.
  {v: {c: 5}}
      ^^^^^^

Props going from a Server Component to a Client Component are serialized. Class instances can't be: Prisma Decimal values, SDK objects (a Stripe or OpenAI response object), Mongoose documents, or your own classes.

usually because

  • Passing a Prisma row with a Decimal column straight to a client table
  • Passing a whole SDK response object instead of the fields you need
  • Objects created with Object.create(null)

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Only plain objects, arrays, primitives and Dates are passed from server to client.

fix

  1. 1.Map to plain fields before passing: { id, name, price: Number(row.price) }
  2. 2.Convert Decimal with .toNumber() or .toString()
  3. 3.Only pass what the client actually renders
src/app/dashboard/page.tsx
const rows = await db.product.findMany();
- return <Table rows={rows} />
+ return <Table rows={rows.map((r) => ({ id: r.id, name: r.name, price: r.price.toNumber() }))} />
prompt for your agent

Next.js says only plain objects can be passed to Client Components. Find the prop that carries a class instance (Prisma Decimal, an SDK object or a custom class) and map it to plain serializable fields on the server before passing it down.

05build erroragents cause this

"use client" must be placed before other expressions

Error: The "use client" directive must be placed before other expressions. Move it to the top of the file to resolve this issue.

The directive only counts as the very first statement in the file. If an import comes first, the file silently stays a Server Component and this error (often with a hook error next to it) appears.

usually because

  • An agent inserted imports above "use client"
  • A license header or 'use strict' line above it (comments are fine, code isn't)

works with Next.js 16.4.3 · React 19.3last verified

fix

  1. 1.Make "use client" the first line of the file, above all imports
  2. 2.Re-run the build: any hook errors from the same file usually disappear too
prompt for your agent

Next.js says the "use client" directive must be placed before other expressions. Move it to line 1 of every file where it's below an import, and don't change anything else.

06build error

export "metadata" from a "use client" page

Error: You are attempting to export "metadata" from a component marked with "use client", which is disallowed. "metadata" must be resolved on the server before the page component is rendered. Keep your page as a Server Component and move Client Component logic to a separate file.

metadata and generateMetadata only work in Server Components. Once a page has "use client" at the top, it can't export them.

usually because

  • The page was turned into a Client Component to fix a hook error
  • An agent added SEO metadata to an existing client page

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Pages stay Server Components and titles come from the Metadata API.

fix

  1. 1.Remove "use client" from page.tsx so it can export metadata
  2. 2.Move the interactive part into a separate "use client" component and render it from the page
prompt for your agent

Next.js refuses to export metadata from a "use client" page. Split it: keep page.tsx as a Server Component that exports metadata, and move the interactive code into a new client component file it renders.

07browser console

async Client Component

Dashboard is an async Client Component. Only Server Components can be async at the moment. This error is often caused by accidentally adding `'use client'` to a module that was originally written for the server.

Client Components can't be async functions. This usually means "use client" was added to a component that awaits data on the server. It can build fine and only fail in the browser.

usually because

  • "use client" added to an async page or component to fix a hook error
  • await fetch() or await db… inside a client file

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Data is fetched with async/await in Server Components, not inside client components.

fix

  1. 1.Keep the async data loading in a Server Component (no "use client")
  2. 2.Pass the loaded data as props to a small client component for the interactive bits
  3. 3.In a Client Component, read a promise passed from the server with React's use() inside <Suspense>
prompt for your agent

React says a component is an async Client Component. Find it, remove "use client" if it fetches data on the server, and move any hooks or event handlers into a separate client child that receives the data as props.

08build error

'server-only' cannot be imported from a Client Component module

Error: You're importing a module that depends on "server-only" into a React Client Component module. This API is only available in Server Components but one of its parents is marked with "use client", so this module is also a Client Component.

A file marked with import "server-only" (on purpose, to keep secrets on the server) ended up in a client bundle. Any file a "use client" file imports becomes client code too.

usually because

  • A client component imports a helper from lib/ that reads env secrets or the database
  • A shared utils file mixes client-safe helpers and server-only ones

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Server-only modules (database clients, secret readers) are never imported into client components.

fix

  1. 1.Don't import that module from the client: call it from a Server Component or Server Action instead
  2. 2.Split the file: client-safe helpers in one module, server-only code in another
  3. 3.Keep the import "server-only" line: it's what caught the leak
prompt for your agent

Next.js blocks a "server-only" module from a Client Component. Show me the import chain from the "use client" file to that module, then split or move the code so the client only gets what it needs through props or a Server Action. Keep the server-only guard.

09build erroragents cause this

Module not found: Can't resolve 'fs'

./src/app/blog/page.tsx:2:1
Error: Module not found: Can't resolve 'fs'
> 2 | import fs from "fs";

Code that uses a Node.js API (fs, path, net, tls, child_process) is being bundled for the browser, where those modules don't exist.

usually because

  • fs or path used inside a "use client" file
  • A client component imports a helper that reads files, or a Node-only package (database drivers, nodemailer)
  • A typo in an import path also gives Module not found, for your own files

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Node-only and server-only modules stay out of client components.

fix

  1. 1.Read files or call Node APIs in a Server Component, route handler or Server Action
  2. 2.Pass the result to the client component as props
  3. 3.Add import "server-only" to modules that must never reach the browser
prompt for your agent

Next.js can't resolve a Node built-in (like fs) in the browser bundle. Trace which "use client" file imports it, move the Node code into a Server Component or Server Action, and add import "server-only" to that module.

10browser console

PrismaClient is unable to run in this browser environment

Error: PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running in `Chrome`).

A Client Component imports your database client (often through lib/db.ts). Database code can only run on the server.

usually because

  • A "use client" component imports db from @/lib/db
  • A shared file exports both db queries and client helpers

works with Next.js 16.4.3 · React 19.3last verified

prevent it · security.mdc (free Cursor Rules Pack): Database modules start with import "server-only", so a client import fails at build time instead of in the browser.

fix

  1. 1.Query the database in a Server Component or Server Action and pass the rows down as plain objects
  2. 2.Add import "server-only" to lib/db.ts so the build fails early next time
src/lib/db.ts
import "server-only";
import { PrismaClient } from "@prisma/client";

export const db = new PrismaClient();
prompt for your agent

Prisma is being bundled into the browser. Find which "use client" file imports the database client, move the query into a Server Component or Server Action, and add import "server-only" to the db module.

11build error

Server Actions must be async functions

Error: Server Actions must be async functions.

Every function exported from a file that starts with "use server" (or marked "use server" inline) is a Server Action, and Server Actions have to be async.

usually because

  • A plain helper or constant exported from actions.ts
  • An agent put "use server" at the top of a utils file

works with Next.js 16.4.3 · React 19.3last verified

fix

  1. 1.Make each exported action async
  2. 2.Move non-action helpers and constants out of the "use server" file
  3. 3.Don't use "use server" to mean "server-only": that's what import "server-only" is for
src/app/actions.ts
"use server";

- export function save(formData: FormData) {
+ export async function save(formData: FormData) {
    // …
  }
prompt for your agent

Next.js says Server Actions must be async. In every "use server" file, make exported actions async and move any non-action exports (helpers, constants, types used at runtime) into a separate module.

12next build (prerender)agents cause this

useSearchParams() should be wrapped in a suspense boundary

⨯ useSearchParams() should be wrapped in a suspense boundary at page "/login". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
Error occurred prerendering page "/login".

A Client Component reads the URL query with useSearchParams on a page Next.js prerenders. The query isn't known at build time, so Next.js needs a <Suspense> boundary to render a fallback there. next dev doesn't complain; next build does.

usually because

  • A login or search page reads ?error= or ?q= with useSearchParams
  • The hook sits in a component used in layout.tsx, so every page fails

works with Next.js 16.4.3 · React 19.3last verified

fix

  1. 1.Wrap the component that calls useSearchParams in <Suspense> in its parent
  2. 2.Or read searchParams in the page (a Server Component prop) and pass the value down
src/app/login/page.tsx
import { Suspense } from "react";
import { LoginForm } from "./login-form"; // calls useSearchParams()

export default function Page() {
  return (
    <Suspense fallback={null}>
      <LoginForm />
    </Suspense>
  );
}
prompt for your agent

next build fails: useSearchParams() should be wrapped in a suspense boundary. Find every component that calls useSearchParams and wrap where it's rendered in <Suspense> with a sensible fallback. Don't make the whole page dynamic to work around it.

13next build (prerender)agents cause this

Next.js encountered runtime / uncached data during prerendering (cacheComponents)

Error: Route "/dashboard": Next.js encountered uncached or runtime data during prerendering.

`fetch(...)`, `cookies()`, `headers()`, `params`, `searchParams`, or `connection()` accessed outside of `<Suspense>` prevents the route from being prerendered…

Ways to fix this:
  - [stream] Provide a placeholder with `<Suspense fallback={...}>` around the data access
  - [cache] … `"use cache"`
  - [block] Set `export const instant = false` to allow a blocking route

With cacheComponents on (the Next.js 16 model), every route gets a prerendered shell. Reading cookies(), headers(), params, searchParams, auth() or an uncached database or fetch call outside <Suspense> would block that shell, so the build stops and lists three ways out.

usually because

  • const session = await auth() at the top of a page
  • A database query in a page with no "use cache" and no <Suspense>
  • Reading searchParams in a layout

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): With cacheComponents on, request-time data (cookies, session, per-user queries) goes inside <Suspense>.

fix

  1. 1.[stream] Move the data access into a child component and wrap it in <Suspense fallback={…}>
  2. 2.[cache] Add "use cache" to data that's the same for every visitor (not for cookies or auth)
  3. 3.[block] For fully per-user pages like a dashboard, add export const instant = false
src/app/dashboard/page.tsx
import { Suspense } from "react";

export default function Page() {
  return (
    <Suspense fallback={<p>Loading…</p>}>
      <Account /> {/* awaits auth() and the DB inside */}
    </Suspense>
  );
}

// or, for a page that is per-user anyway:
// export const instant = false;
prompt for your agent

next build fails because a route reads runtime or uncached data outside <Suspense> (cacheComponents is on). For this route, move the cookies/auth/DB access into a child component wrapped in <Suspense>, or add "use cache" if the data is the same for everyone, or export const instant = false if the page is fully per-user. Explain which one you picked.

14silent bugagents cause this

params.slug is undefined (params is a Promise)

Property 'slug' does not exist on type 'Promise<{ slug: string; }>'.  ·  page renders "undefined"

Since Next.js 15, params and searchParams are Promises. Code from older tutorials reads params.slug directly. In our Next.js 16.4.3 test build that didn't fail at all: the page just rendered "undefined".

usually because

  • The page is typed { params: { slug: string } } (the old shape), so TypeScript doesn't catch it
  • Agents trained on Next.js 13/14 examples
  • Same for searchParams, cookies() and headers(): all async now

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): Params and searchParams are awaited: const { slug } = await params.

fix

  1. 1.Type params as a Promise and await it in Server Components
  2. 2.In a Client Component, unwrap it with React's use(params)
  3. 3.Search the codebase for params. and searchParams. without an await
src/app/blog/[slug]/page.tsx
export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  // …
}
prompt for your agent

This is a Next.js 16 app, where params, searchParams, cookies() and headers() are async. Find every page, layout, route handler and generateMetadata that reads them synchronously, type them as Promises and await them (or use() in Client Components). List each file you change.

15build error

missing generateStaticParams() with output: export

Error: Page "/blog/[slug]" is missing "generateStaticParams()" so it cannot be used with "output: export" config.

A static export has no server, so every dynamic route has to list its pages at build time.

usually because

  • A new [slug] or [id] route in a site deployed as static files
  • generateStaticParams exists but sits in a "use client" page

works with Next.js 16.4.3 · React 19.3last verified

fix

  1. 1.Export generateStaticParams() from the page and return every slug
  2. 2.If the route really needs a server (per-user data), drop output: export and deploy to a host that runs Next.js
src/app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await getPosts();
  return posts.map((p) => ({ slug: p.slug }));
}
prompt for your agent

next build fails because a dynamic route has no generateStaticParams and the app uses output: export. Add generateStaticParams that returns every value for this route from the same data source the page reads.

16dev overlay

next/image hostname is not configured

Error: Invalid src prop (https://avatars.githubusercontent.com/u/1) on `next/image`, hostname "avatars.githubusercontent.com" is not configured under images in your `next.config.js`

next/image only optimizes remote images from hosts you allow. Avatars from GitHub or Google sign-in, Stripe product images and CMS images all need an entry.

usually because

  • Showing session.user.image from an OAuth provider
  • Images from a CMS, S3 bucket or Supabase Storage

works with Next.js 16.4.3 · React 19.3last verified

fix

  1. 1.Add the host to images.remotePatterns in next.config.ts
  2. 2.Be specific (protocol, hostname, path) instead of allowing every host
next.config.ts
const nextConfig = {
  images: {
    remotePatterns: [new URL("https://avatars.githubusercontent.com/**")],
  },
};
prompt for your agent

next/image rejects a remote hostname. Add a specific images.remotePatterns entry in next.config.ts for this host (protocol, hostname and a path pattern if possible). Don't allow all hosts.

17browser consoleagents cause this

Hydration failed: server HTML didn't match the client

Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client.
  · A tree hydrated but some attributes of the server rendered HTML didn't match the client properties.

React rendered the page on the server, then got different output in the browser. Something in render depends on the time, randomness, the browser or the user's locale.

usually because

  • new Date(), Date.now() or Math.random() in render
  • if (typeof window !== "undefined") branches, or reading localStorage during render
  • toLocaleString() with a different server and browser locale or time zone
  • Invalid HTML nesting like <p> inside <p> or <div> inside <p>
  • Browser extensions that add attributes to <html> or <body>

works with Next.js 16.4.3 · React 19.3last verified

fix

  1. 1.Move browser-only values into useEffect, or render them in a Client Component loaded with next/dynamic and ssr: false
  2. 2.Format dates with an explicit timeZone, or on the server only
  3. 3.Fix invalid nesting the error points at
  4. 4.For extension attributes only: suppressHydrationWarning on <html> (it only applies one level deep)
prompt for your agent

React reports a hydration mismatch. Find what renders differently on the server and in the browser (dates, random values, window/localStorage checks, locale formatting, invalid HTML nesting) and fix the cause. Don't add suppressHydrationWarning except for extension attributes on <html> or <body>.

18build warningagents cause this

The "middleware" file convention is deprecated

⚠ The "middleware" file convention is deprecated. Please use "proxy" instead.

  To migrate automatically, run:
  npx @next/codemod@canary middleware-to-proxy .

Next.js 16 renamed middleware.ts to proxy.ts. Agents keep creating middleware.ts because most examples predate the rename. Proxy runs on the Node.js runtime, and the runtime option isn't allowed in proxy files.

usually because

  • An agent added auth or redirects in middleware.ts
  • Code copied from Next.js 13–15 or Auth.js v4 examples

works with Next.js 16.4.3 · React 19.3last verified

prevent it · nextjs-app-router.mdc (free Cursor Rules Pack): On Next.js 16 the agent writes proxy.ts exporting proxy instead of middleware.ts.

fix

  1. 1.Run npx @next/codemod@canary middleware-to-proxy . or rename the file and the exported function to proxy
  2. 2.Remove any export const runtime = "edge" from it
  3. 3.Keep matchers in export const config as before
src/proxy.ts
import { NextResponse, type NextRequest } from "next/server";

export function proxy(request: NextRequest) {
  return NextResponse.next();
}

export const config = { matcher: ["/dashboard/:path*"] };
prompt for your agent

This is Next.js 16: middleware.ts is deprecated in favor of proxy.ts. Migrate it (rename the file and the exported function to proxy, keep the matcher config, remove any runtime export) and check nothing else imports the old file.

19build erroragents cause this

npm ci: package.json and package-lock.json are not in sync

npm error `npm ci` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with `npm install` before continuing.

Someone (often an agent fixing something else) changed the next version in package.json without updating package-lock.json, so a clean install refuses to run. The lockfile is what pins the exact version you tested: a range like ^16.4.3 in package.json allows any later 16.x, so without a committed lockfile each install can build against a different Next.js.

usually because

  • An agent edited the next, react or eslint-config-next version in package.json, or ran npm install next@latest, while fixing something else
  • package-lock.json is in .gitignore, wasn't committed, or was deleted to "fix" an install error
  • next, eslint-config-next and react changed in different commits

works with Next.js 16.4.3 · React 19.3last verified

prevent it · 00-workflow.mdc (free Cursor Rules Pack): The agent doesn't bump next, react or other framework packages unless the task asks for it.

fix

  1. 1.See what's installed: npm ls next react react-dom
  2. 2.Pin the exact version you last tested (use yours): npm pkg set dependencies.next=16.4.3 devDependencies.eslint-config-next=16.4.3, run npm install to update package-lock.json, then commit both files together
  3. 3.Use npm ci in CI and deploy builds so installs match the lockfile exactly
  4. 4.Upgrade on purpose in its own branch: npx @next/codemod@canary upgrade latest, then run the build and tests
terminal
npm ls next react react-dom
npm pkg set dependencies.next=16.4.3 devDependencies.eslint-config-next=16.4.3
npm install
git add package.json package-lock.json
git commit -m "Pin next to 16.4.3"
npm ci && npm run build
prompt for your agent

npm ci fails because package.json and package-lock.json are out of sync on next. Don't upgrade anything. Find which commit changed the next/react/eslint-config-next versions, restore the last version the app built with, pin it as an exact version (no ^), regenerate the lockfile with npm install, and confirm npm ci && npm run build pass. List every version you changed.

20browser console

Maximum update depth exceeded

Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

A component keeps updating its own state in a loop, so React stops it. It's a React error, but agents cause it often when they wire up effects.

usually because

  • setState in a useEffect with no dependency array
  • An object or array created during render used as an effect dependency
  • onClick={setOpen(true)} instead of onClick={() => setOpen(true)}

works with Next.js 16.4.3 · React 19.3last verified

fix

  1. 1.Give the effect a dependency array, and only list values that really change
  2. 2.Memoize object or array dependencies, or depend on their primitive fields
  3. 3.Pass a function to event props instead of calling it
prompt for your agent

React hit Maximum update depth exceeded. Find the effect or handler that sets state on every render, explain the loop in one sentence, and fix it with correct dependencies or by passing a function instead of calling it.

03Or start from code that already builds

A Next.js 16 SaaS your agent can't easily derail.

Skip the setup. The VibeBoot SaaS Starter gives you auth, Stripe and a database already wired on Next.js 16.4.3, with AGENTS.md and .cursor/rules that keep your agent on the Next.js 16 conventions. $49, one-time.

14-day money-back guarantee · lifetime updates

See everything that's inside →
  • proxy.ts · already uses the Next.js 16 proxy convention, no middleware.ts deprecation warning
  • cacheComponents on · the dashboard shows the export const instant = false pattern, and AGENTS.md explains when to use <Suspense> instead
  • Agent rules · AGENTS.md, CLAUDE.md and .cursor/rules: Server Components by default, "use client" only for interactivity
  • Database on the server · Prisma lives in lib/db.ts and the rules say to query it only from Server Components or Server Actions
  • Checks included · npm run typecheck, lint and test (Vitest) scripts, so the agent can verify its own changes

FAQ

Why does my Next.js app work in next dev but fail in next build?

next build prerenders every page it can. That's when Next.js checks things dev mode lets slide: useSearchParams without a <Suspense> boundary, event handlers rendered by Server Components, class instances passed to Client Components, and (with cacheComponents on) cookies(), auth() or database reads outside <Suspense>. Run next build locally before you push.

Why do AI coding agents keep causing these errors?

Most Next.js code they learned from predates the App Router defaults of Next.js 15 and 16: everything is a Server Component unless marked "use client", params and searchParams are Promises, and middleware.ts is now proxy.ts. Telling the agent your exact Next.js version and these rules in AGENTS.md or .cursor/rules prevents most of them.

Should I just add "use client" to the page?

Usually not. It silences hook errors but turns the whole page into client code: you can't export metadata, async data loading breaks (async Client Component) and more JavaScript ships to the browser. Move only the interactive part into its own "use client" file.

Is anything I paste sent to a server?

No. The matcher is plain JavaScript in this page. Nothing you paste is stored or sent anywhere.

Which Next.js version is this for?

The App Router in Next.js 16. Each error was reproduced in a test app on Next.js 16.4.3 · React 19.3 with next build on October 24, 2026, or taken from the error text shipped in the next package. Most entries also apply to Next.js 15.

Sources: errors reproduced with next build on Next.js 16.4.3 · React 19.3, the error text and docs shipped in the next package, and the Next.js docs on Server and Client Components, proxy and hydration mismatches. Checked October 24, 2026. Spotted a mistake? Email [email protected].

Also free: Auth.js error fixer · Stripe webhook fixer · newsletter

$ fixed it? get the next one first

New fixes for what AI agents break, by email.

When we add a fix or a Cursor rule for a new Next.js, Auth.js, Prisma or Stripe break, it goes out in the VibeBoot newsletter. Free, occasional, unsubscribe in one click.

Subscribe free

> More free tools

All tools →