I'm working on a Next.js 15 app using the new App Router (app directory) with dynamic route localization. I have a [locale] directory where I handle multiple language routes, and I use the params object to access the locale value. However, I keep getting the following error when trying to access params.locale:
Error: Route "/[locale]" used `params.locale`. `params` should be awaited before using its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis
at locale (webpack:///app/[locale]/layout.tsx?a262:30:34)
Code Structure Here's the structure of my app:
app/
├── [locale]/
│ ├── layout.tsx // Root layout for [locale] dynamic route
│ └── page.tsx // Main page component for [locale] dynamic route
locales/
├── en/
│ └── common.json // English translations
├── lt/
│ └── common.json // Lithuanian translations
i18Config.js // i18n configuration with available locales
i18n.js // i18n initialization file
TranslationsProvider.js // Translation provider component
middleware.js // Middleware to handle locale-based redirection
In app/[locale]/layout.tsx, I want to access the locale value from params and pass it to different components. I have tried various ways to access params, but the error persists.
Here's what my layout.tsx file looks like:
import "@/styles/global.css";
import { Outfit } from "next/font/google";
import { Providers } from "./providers";
import i18nConfig from "../../i18nConfig";
import { dir } from "i18next";
const outfit = Outfit({
subsets: ["latin"],
weight: ["300", "400", "500", "600", "700", "800"],
style: ["normal"],
});
export function generateStaticParams() {
return i18nConfig.locales.map((locale) => ({ locale }));
}
export default async function RootLayout({
children,
params: { locale },
}: {
children: React.ReactNode;
params: { locale: string };
}) {
return (
<html
lang={locale}
dir={dir(locale)}
suppressHydrationWarning
className={outfit.className}
>
<body className="bg-background">
<Providers>{children}</Providers>
</body>
</html>
);
}
The error suggests that params should be "awaited," even though params is an object and not a promise, so await params doesn’t make sense here. I’ve seen other posts mentioning that destructuring in async functions can cause issues with params in Next.js, but accessing params directly also didn’t work for me. Restarting the server after every change didn’t resolve the issue either.
How can I correctly access params.locale in a dynamic route layout without getting this error? Is there a workaround or configuration I’m missing? Any insight would be greatly appreciated. Thank you!
I just found the problem (and it makes no sense at all).
This is the layout.tsx
code and it seems to be correct:
export default async function RootLayout({
children,
params,
}: RootLayoutProps) {
const { lang } = await params
return (
<html lang={lang}>
<body>{children}</body>
</html>
)
}
In my case, the icon.png
file was triggering the warning.
With warning:
/src
/app
/[lang]
/layout.tsx
/icon.png
Without warning:
/src
/app
/icon.png
/[lang]
/layout.tsx
That's it:
/app/[lang]/icon.png
- Warning/app/icon.png
- No warning