Question

Build fails on Vercel: useSearchParams() should be wrapped in a suspense boundary at page /login

Solved · 522 viewsasked by harriet_g

npm run dev works perfectly. Vercel build dies with this:

The login page reads ?next=/dashboard to redirect after login. The whole page.tsx is "use client".

What I’ve tried

Claude wrapped the whole page return in <Suspense> inside the same component. Same error.

Comment
Same error on my /search page yesterday, following this. lucy_hart

3 answers

Marked as helpful by the asker
dev_ana

Suspense has to be above the component that calls useSearchParams, not inside it. Split it:

// app/login/page.tsx (server component, no "use client")
import { Suspense } from "react";
import LoginForm from "./login-form";

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

login-form.tsx gets the "use client" and the useSearchParams call. Dev doesn't catch this because it renders on request; only the production build tries to prerender the page statically.

Alternative: page.tsx receives searchParams as a prop (it's a promise in Next 15, so await it) and passes next down. No client hook needed at all.

Comment
Split it into two files, build is green. The 'dev renders on request' explanation finally made the dev vs build difference click for me. harriet_g
Clearest explanation of this error I've read. tom_brewer
tom_brewer

If the error says at page "/_not-found" instead of your own page, the hook is in something your root layout renders (a navbar with a search box, usually). Same fix, wrap that component in Suspense in the layout.

Comment
mei_lin

+1 to the searchParams prop route. For a login redirect you don't need client-side reactivity, reading it on the server is simpler and nothing to wrap.

Comment