Next.js 15 + next-intl: Build fails on Firebase App Hosting when prerendering a route (useLocale crash on /sell)

Hi everyone,

I’m setting up a bilingual Next.js app (German/English) with next-intl. Locally everything works perfectly, including the language switcher and localized routes. However, when I deploy to Firebase App Hosting, the build fails during prerendering of one route.

Environment

  • Next.js: 15.3.3 (App Router)

  • Node.js (from Firebase buildpack): 22.19.0

  • next-intl: (v3.x)

  • Hosting: Firebase App Hosting (buildpacks)

  • Routing: app directory with locale segment (e.g., app/[locale]/...)

What I’m trying to do

  • Two locales: de and en

  • Server Components by default, Client Components where needed

  • Using next-intl’s useLocale in client components and server APIs (getTranslations) in server components

  • Works locally: npm run build and npm run start succeed; language switcher behaves correctly.

What actually happens on deploy

Firebase build starts fine, but crashes while prerendering /sell:

> next build
   ▲ Next.js 15.3.3
   Creating an optimized production build ...
 ✓ Compiled successfully
   Generating static pages (0/120) ...
Error occurred prerendering page "/sell". Read more: https://nextjs.org/docs/messages/prerender-error
Error:
    at s (/workspace/.next/server/chunks/1622.js:28:89259)
    at t.useLocale (/workspace/.next/server/chunks/1622.js:28:89331)
    at t.default (/workspace/.next/server/chunks/1622.js:28:114344)
    ...
Export encountered an error on /sell/page: /sell, exiting the build.
⨯ Next.js build worker exited with code: 1

So the build fails with a prerender error seemingly related to useLocale being evaluated at build time.

Project structure (relevant bits)

app/
  [locale]/
    layout.tsx
    sell/
      page.tsx
  components/
    LocaleSwitcher.tsx   // 'use client' + useLocale()

next-intl usage (simplified)

// app/[locale]/layout.tsx

import {unstable_setRequestLocale} from 'next-intl/server';

export function generateStaticParams() {
  return [{locale: 'en'}, {locale: 'de'}];
}

export default function RootLayout({
  children,
  params: {locale}
}: {
  children: React.ReactNode;
  params: {locale: string};
}) {
  unstable_setRequestLocale(locale);
  return <html lang={locale}><body>{children}</body></html>;
}

// app/[locale]/sell/page.tsx (Server Component)

import {getTranslations} from 'next-intl/server';

export default async function SellPage() {
  const t = await getTranslations('Sell');
  return <h1>{t('title')}</h1>;
}

// components/LocaleSwitcher.tsx (Client Component)

'use client';
import {useLocale} from 'next-intl';

export default function LocaleSwitcher() {
  const locale = useLocale();
  return <span>{locale}</span>;
}

What I’ve tried so far

  1. Disable prerender for the failing route
    Adding to app/[locale]/sell/page.tsx:

    export const dynamic = 'force-dynamic';
    export const revalidate = 0;
    
    

    ➜ This avoids build-time evaluation and lets the route render at request time, which works. But I’d prefer to keep SSG if possible.

  2. Audit imports on /sell
    Ensured there’s no direct window, document, localStorage, headers(), or cookies() usage in server code. Any client-only logic is behind 'use client' and useEffect.

  3. Static params & locale segment
    Confirmed generateStaticParams returns both locales and the route is under [locale].

  4. Local reproduction under Node 22
    Built locally with Node 22.19 via nvm and couldn’t reproduce the crash—the error only appears in Firebase’s build environment.

Questions

  1. Is there a known issue with next-intl + Next 15 on Firebase App Hosting where useLocale (or related code) gets executed during static export unexpectedly?

  2. Are there Firebase buildpack settings that force static generation of certain routes even if they depend on request locale?

  3. What’s the recommended way to keep /sell statically generated while using next-intl—and avoid useLocale being evaluated at build time?

  4. Any guidance on diagnosing which import in the /sell tree is causing useLocale to run on the server during prerender? (The stack trace points into compiled chunks.)

Ideal outcome

  • Keep /sell as SSG for both de and en.

  • Ensure useLocale is only used in client components at runtime.

  • Successful next build in Firebase without needing dynamic = 'force-dynamic'.

Thanks a lot for any pointers! I can share more snippets if needed.