oxc-project/oxc · warning · OxcDiagnostic
Prevent client components from being async functions.
Error message
Prevent client components from being async functions.
What it means
Warning from oxlint rule `nextjs/no-async-client-component`. React only supports async components on the server; a component in a file with a `'use client'` directive runs in the browser, where async components cannot be rendered or hydrated. The rule flags async function components in client context at lint time, before it becomes a hydration or runtime failure.
Source
Thrown at crates/oxc_linter/src/rules/nextjs/no_async_client_component.rs:12
use oxc_ast::{
AstKind,
ast::{BindingPattern, ExportDefaultDeclarationKind, Expression, Statement},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{ast_util::get_declaration_of_variable, context::LintContext, rule::Rule};
fn no_async_client_component_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Prevent client components from being async functions.")
.with_help("See: https://nextjs.org/docs/messages/no-async-client-component")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoAsyncClientComponent;
declare_oxc_lint!(
/// ### What it does
///
/// Prevents the use of async functions for client components in Next.js applications.
/// This rule checks for any async function that:
/// - Is marked with "use client" directive
/// - Has a name starting with an uppercase letter (indicating it's a component)
/// - Is either exported as default or assigned to a variable
///
/// ### Why is this bad?
///View on GitHub (pinned to e1e7af627c)
Solutions
- Remove `'use client'` so the page becomes an async server component (best fix when no hooks/state are used).
- Keep the client component but drop `async`, and load data with `useEffect` + fetch, SWR, or React Query.
- Move the async fetching into a server component and pass results down as props.
Example fix
// before
'use client';
export default async function Page() {
const data = await getData();
return <pre>{JSON.stringify(data)}</pre>;
}
// after
export default async function Page() {
const data = await getData();
return <pre>{JSON.stringify(data)}</pre>;
} Defensive patterns
Strategy: validation
Validate before calling
// fail on async exports in client files: // rg -l "^'use client'" app components | xargs rg -n 'export (default )?async function'
Prevention
- Decide per file: server (async allowed, no directives) or client (no async exports) — never both.
- Do data fetching in server components and pass props; use SWR/React Query in client ones.
- Add an oxlint CI job with the nextjs plugin so an accidental `'use client'` + async page fails fast.
When it happens
Trigger: A file whose top-level contains `'use client'` (tracked through the module graph) that declares or exports an `async function` used as a component, including `export default async function Page()`.
Common situations: Adding `await` data loading to a page and also marking it `'use client'` for hooks or state; copying an async server page into a client widget; mixing React Server Component patterns from tutorials.
Related errors
- Change to `throw new TypeError(...)`
- Promise executor functions should not be `async`.
- Unexpected `await` inside a loop.
- Function parameter(s) use the `done` argument
- A font-display parameter is missing (adding `&display=option
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/9e19f20c4821537e.
Report an issue: GitHub.