Next.js errors, explained and fixed
The errors that stop a build or break a page, with the cause underneath each one - not just the incantation that makes it go away.
Hydration failed because the initial UI does not match what was rendered on the server.Hydration Failed Because the Initial UI Does Not Match
React found a difference between server HTML and the first client render. Find the node, then the cause.
useSearchParams() should be wrapped in a suspense boundary at page "/". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailoutuseSearchParams() Should Be Wrapped in a Suspense Boundary
One hook opted the whole page out of static rendering. Suspense limits the blast radius.
Dynamic server usage: Route /dashboard couldn't be rendered statically because it used `cookies`.Route Couldn't Be Rendered Statically Because It Used Cookies
One request-time API took the whole route dynamic. Find the call, then decide where it belongs.
Error: Event handlers cannot be passed to Client Component props. <button onClick={function onClick}>. If you need interactivity, consider converting part of this to a Client Component.Event Handlers Cannot Be Passed to Client Component Props
A function was passed from a Server Component to a Client one. Move the boundary, do not raise it.
Error: Invalid src prop (https://cdn.example.com/photo.jpg) on `next/image`, hostname "cdn.example.com" is not configured under images in your next.config.jsInvalid src prop - hostname Is Not Configured Under images
next/image only optimises hosts you have allowed. The allowlist is a bill control, not red tape.
ReferenceError: window is not definedReferenceError: window Is Not Defined
Server rendering has no window object. Where the code runs decides which of three fixes applies.
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.Only Plain Objects Can Be Passed to Client Components
A class instance crossed the boundary. Send data, not objects with behaviour attached.
Module not found: Can't resolve 'fs'Module Not Found: Can't Resolve 'fs'
Server-only code reached a client bundle. Follow the import chain, do not stub the module.
You're importing a component that needs `useState`. This React hook only works in a client component. To fix, mark the file (or its parent) with the `"use client"` directive.You're Importing a Component That Needs useState
The fix is right; the placement usually is not. Mark the leaf, not the page.
Error: NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mountedNextRouter Was Not Mounted
next/router does not exist in the App Router. next/navigation replaces it, with a different API.
Error: NEXT_REDIRECTredirect() Does Nothing Inside a try/catch
redirect() throws by design. Catching it cancels the navigation and logs a fake error.
Warning: Text content did not match. Server: "2 hours ago" Client: "3 hours ago"Text Content Does Not Match Server-Rendered HTML
A text node differed between the two renders. Relative times and locale formatting cause most of them.
Error: Failed to parse src "products/photo.jpg" on `next/image`, if using relative image it must start with a leading slash "/" or be an absolute URL (http:// or https://)Failed to Parse src on next/image
next/image needs a leading slash or a full URL. A bare relative path has nothing to resolve against.
You're importing a component that needs next/headers. That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component.You're Importing a Component That Needs next/headers
A server-only API ended up under a 'use client' parent. Move the read up, not the directive down.
Error: The default export is not a React Component in "/products/[id]/page"The Default Export Is Not a React Component
A route file exported something that is not a component - or exported it the wrong way.
Why these pages exist
Most answers to a Next.js error are a snippet that makes the message disappear. Sometimes that is the fix. More often it moves the problem somewhere the error handler cannot see it, and you meet it again two sprints later wearing a different message.
Each page here gives the cause first - what the framework was actually doing when it complained - then the fix that follows from it, then the ones that look like fixes and are not.
They come out of audits. Every error listed is one we have found in somebody's production codebase, usually more than once.
