This error occurs in Next.js when using async/await operations in a Server Component without declaring the component function as async. React Server Components require the async keyword to use await syntax.
This error appears in Next.js 13+ applications when you attempt to use the `await` keyword inside a component function that is not declared as `async`. React Server Components introduce a powerful feature that allows you to fetch data directly in your components using async/await syntax, but only if the component function itself is marked as async. The error serves as a guardrail to ensure proper async function syntax. In traditional React, components could not be async functions. With React Server Components in Next.js, this limitation is lifted for server-side components, allowing you to write cleaner data-fetching code without useEffect hooks or separate API routes. This is one of the fundamental differences between Server Components and Client Components. Server Components can be async and await data directly, while Client Components (those with 'use client') cannot use async/await at the component level.
The simplest fix is to add the async keyword before your component function declaration:
// ❌ Incorrect - missing async
export default function Page() {
const data = await fetch('https://api.example.com/data');
return <div>{JSON.stringify(data)}</div>;
}
// ✅ Correct - component is async
export default async function Page() {
const data = await fetch('https://api.example.com/data');
const json = await data.json();
return <div>{JSON.stringify(json)}</div>;
}This works for all Server Components including pages, layouts, and regular component files.
Check that your component file does not have the 'use client' directive at the top. Client Components cannot be async:
// ❌ This will NOT work
'use client';
export default async function ClientComponent() {
const data = await fetch('...'); // Error!
return <div>{data}</div>;
}If you need interactivity (hooks, event handlers) AND async data:
1. Remove 'use client' and make the component async (Server Component)
2. Pass the fetched data to a Client Component as props
3. Or use traditional client-side data fetching (useEffect, React Query, SWR)
// ✅ Correct approach - fetch in Server Component
async function ParentServerComponent() {
const data = await fetch('...');
const json = await data.json();
return <InteractiveClientComponent data={json} />;
}
// Separate file: InteractiveClientComponent.tsx
'use client';
export default function InteractiveClientComponent({ data }) {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{data.title}</button>;
}If using TypeScript, make sure your component returns a Promise that resolves to JSX:
// Explicit return type (optional but helpful)
export default async function Page(): Promise<JSX.Element> {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return (
<div>
<h1>Data from API</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}For components with props, type them normally:
interface PageProps {
params: { id: string };
searchParams: { sort?: string };
}
export default async function Page({ params, searchParams }: PageProps) {
const { id } = params;
const data = await fetch(`https://api.example.com/items/${id}`);
const item = await data.json();
return <div>{item.name}</div>;
}In Next.js 15, params and searchParams are now promises that must be awaited:
// Next.js 15 - params is a Promise
export default async function Page({
params
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params;
const data = await fetch(`https://api.example.com/${slug}`);
return <div>{JSON.stringify(data)}</div>;
}
// For searchParams
export default async function SearchPage({
searchParams
}: {
searchParams: Promise<{ q?: string }>
}) {
const { q } = await searchParams;
const results = await fetch(`https://api.example.com/search?q=${q}`);
return <div>Results for {q}</div>;
}This change was introduced to support async route params and improve type safety.
Server vs Client Component Async Patterns
Server Components and Client Components have fundamentally different approaches to async operations:
- Server Components: Can be async functions, await data directly, render once on the server per request
- Client Components: Cannot be async, must use hooks (useEffect, useSWR, React Query) for data fetching, run in the browser
Performance Considerations
Async Server Components block rendering until all awaited operations complete. For better performance:
// ❌ Sequential fetching (slow)
async function Page() {
const user = await fetchUser();
const posts = await fetchPosts();
return <div>...</div>;
}
// ✅ Parallel fetching (fast)
async function Page() {
const [user, posts] = await Promise.all([
fetchUser(),
fetchPosts()
]);
return <div>...</div>;
}Streaming with Suspense
For slow data requests, wrap components in Suspense to stream content progressively:
export default function Page() {
return (
<div>
<h1>Fast Content</h1>
<Suspense fallback={<Loading />}>
<SlowAsyncComponent />
</Suspense>
</div>
);
}
async function SlowAsyncComponent() {
const data = await slowFetch();
return <div>{data}</div>;
}This prevents the entire page from being blocked by slow data sources.
Common Migration Pattern
When converting from Client Component with useEffect to Server Component:
// Before: Client Component
'use client';
import { useEffect, useState } from 'react';
export default function OldComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data').then(r => r.json()).then(setData);
}, []);
if (!data) return <div>Loading...</div>;
return <div>{data.title}</div>;
}
// After: Server Component
export default async function NewComponent() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return <div>{data.title}</div>;
}This eliminates loading states, reduces client-side JavaScript, and improves SEO since content is server-rendered.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite