useSearchParams() & suspense boundary
Used in this guide:Next.js 15.3.3
Vercel
Error:
useSearchParams() should be wrapped in a suspense boundary at page '/payment-success'. Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
Reason
When using useSearchParams() inside a Server Component (like a page.tsx) in Next.js 13+ with App Router, you might run into this error
This happens even when you've added 'use client' and wrapped your component with <Suspense>. Here’s why it happens and how to fix it properly.
What Causes the Error?
- You’re calling useSearchParams() directly in a page.tsx, which by default is a Server Component.
- Even if you add 'use client' at the top and wrap parts in <Suspense>, the page is still considered a Server Component, and trying to use useSearchParams() forces a Client-Side Rendering (CSR) bailout.
- Vercel throws this warning because you're mixing Server and Client logic incorrectly.
The Proper Fix
- Keep your page.tsx as a Server Component (no "use client" at the top).
- Move the logic that uses useSearchParams() into a separate Client Component.
- Import that component into your page.tsx and wrap it with <Suspense> if needed.
Example (incorrect version)
'use client';
import { useSearchParams } from 'next/navigation';
export default function PaymentSuccessPage() {
const params = useSearchParams();
const status = params.get('status');
return <div>Payment status: {status}</div>;
}After (Correct Version with Separated Client Component)
import { Suspense } from 'react';
import PaymentStatusClient from './PaymentStatusClient';
export default function PaymentSuccessPage() {
return (
<Suspense fallback={<div>Loading status...</div>}>
<PaymentStatusClient />
</Suspense>
);
}'use client';
import { useSearchParams } from 'next/navigation';
export default function PaymentStatusClient() {
const params = useSearchParams();
const status = params.get('status');
return <div>Payment status: {status}</div>;
}