Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getLanguage breaks with Next.js 15 due to async request API breaking change #245

Closed
asterikx opened this issue Oct 17, 2024 · 23 comments
Closed

Comments

@asterikx
Copy link

Starting with latest RC of Next.js 15 (RC 2), the request APIs including headers() is async: https://nextjs.org/blog/next-15-rc2#async-request-apis-breaking-change

This change breaks the getLanguage() function from @inlang/paraglide-next (on the server):

https://github.com/opral/monorepo/blob/a0aaf620811b580e478a3d4add22e4c5475cbcc3/inlang/source-code/paraglide/paraglide-next/src/app/getLanguage.server.ts#L14

The getLanguage() function (and therefore every function that uses it) would have to be changed to an async function.

Copy link
Member

I feared that the Next 15 changes will impact the next adapter. Will have to wait for the metaframework overhaul project

@mrthinger
Copy link

I feared that the Next 15 changes will impact the next adapter. Will have to wait for the metaframework overhaul project

any idea on the eta for that?

@samuelstroschein
Copy link
Member

Estimate is Q1 2025 for #217.

But I can invest time into reviewing, merging, and publishing a PR. Thus, if anyone wants to fix NextJS 15 support, please open a PR :)

@asterikx
Copy link
Author

I did patch the package locally (seems to work fine). I can create a PR tomorrow.

@iStorry
Copy link

iStorry commented Oct 22, 2024

I did patch the package locally (seems to work fine). I can create a PR tomorrow.

I tried making some changes, but I'm encountering other errors for some reason.

async function getLanguage() {
    try {
        const allHeader = await headers();
        const langHeader = allHeader.get(PARAGLIDE_LANGUAGE_HEADER_NAME);
        ....

@harrisrobin
Copy link

would appreciate if you could share your fix on this @asterikx . I'm experiencing issues as well.

@tconroy
Copy link

tconroy commented Oct 23, 2024

+1 to above, running into this. would be great to push up as a branch we can install from in the meantime.

@tconroy
Copy link

tconroy commented Oct 26, 2024

I've opened a PR here: opral/monorepo#3188

Unfortunately I wasn't able to run/test it locally, but perhaps it's a useful jumping off point to resolve this issue.

@asterikx
Copy link
Author

Here's my patch file created using bun patch @inlang/paraglide-next: @inlang%[email protected]

Seems to work just fine for me at the moment.

@gerardmarquinarubio
Copy link

Bumping for visibility

Here's my patch file created using bun patch @inlang/paraglide-next: @inlang%[email protected]

Seems to work just fine for me at the moment.

Do you know how to use the patchfile from bun directly? Couldn't find any documentation.

@tconroy
Copy link

tconroy commented Oct 29, 2024

@gerardmarquinarubio add a patchedDependencies key to your package.json, with the value being an object that maps `"dependency@version": "patches/patchName.patch" file.

Something like this (typing on phone so apologies for typos):

{
  "patchedDependencies": {
    "@inlang/[email protected]": "patches/@inlang/[email protected]"
  }
}

@samuelstroschein
Copy link
Member

opral/monorepo#3188 has been merged and published as v0.7. Thanks @tconroy for the PR!

CleanShot 2024-10-29 at 17 27 01@2x

@gerardmarquinarubio
Copy link

gerardmarquinarubio commented Oct 29, 2024

I'm getting Error: headers was called outside a request scope. Just as I updated to paraglide-next@latest.

Will try to give a repo to reproduce in a few minutes.

@gerardmarquinarubio
Copy link

gerardmarquinarubio commented Oct 29, 2024

@samuelstroschein @tconroy

Clone the repo, bun dev, you will get the error.

https://github.com/gerardmarquinarubio/paraglide-next-headers-bug

The minimal repo was as easy to reproduce as just creating a next-app using the CLI and defaults and initializing paraglide-next through the CLI.

@samuelstroschein
Copy link
Member

@gerardmarquinarubio thanks for the repro. Highly appreciated if you can open a follow up pr to fix the issue

@asterikx
Copy link
Author

asterikx commented Oct 30, 2024

I'm getting more errors:

  12 | async function getLanguage() {
  13 |     try {
> 14 |         const langHeader = await headers().get(PARAGLIDE_LANGUAGE_HEADER_NAME);
     |                                       ^
  15 |         const lang = isAvailableLanguageTag(langHeader) ? langHeader : sourceLanguageTag;
  16 |         return lang;
  17 |     }
 ⨯ unhandledRejection: Error: `headers` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context

Instead of:

 const langHeader = await headers().get(PARAGLIDE_LANGUAGE_HEADER_NAME);

it needs to be:

const langHeader = (await headers()).get(PARAGLIDE_LANGUAGE_HEADER_NAME);

Copy link
Member

Yeah that makes sense. I'll fix it.

Copy link
Member

Released as 0.7.1

@iStorry
Copy link

iStorry commented Oct 31, 2024

Released as 0.7.1

Error: `headers` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context
    at getExpectedRequestStore (webpack-internal:///(shared)/./node_modules/next/dist/esm/server/app-render/work-unit-async-storage.external.js:26:11)
    at headers (webpack-internal:///(middleware)/./node_modules/next/dist/esm/server/request/headers.js:76:127)
    at getLanguage (webpack-internal:///(middleware)/./node_modules/@inlang/paraglide-next/dist/paraglide-next/src/app/getLanguage.server.js:21:88)
    at eval (webpack-internal:///(middleware)/./node_modules/@inlang/paraglide-next/dist/paraglide-next/src/app/providers/LanguageProvider.js:15:148)
    at eval (webpack-internal:///(middleware)/./node_modules/@inlang/paraglide-next/dist/paraglide-next/src/app/providers/LanguageProvider.js:16:3)
    at (middleware)/./node_modules/@inlang/paraglide-next/dist/paraglide-next/src/app/providers/LanguageProvider.js (/my-app/.next/server/src/middleware.js:258:1)
    at __webpack_require__ (my-app/.next/server/edge-runtime-webpack.js:37:33)
    at fn (my-app/.next/server/edge-runtime-webpack.js:281:21)
    at eval (webpack-internal:///(middleware)/./node_modules/@inlang/paraglide-next/dist/app/index.server.js:13:111)

The feature works well, but I keep getting the same problem when I build or use the cold star mode.

@asterikx
Copy link
Author

Yes, I unfortunately keep getting the same error as well:

  12 | async function getLanguage() {
  13 |     try {
> 14 |         const langHeader = (await headers()).get(PARAGLIDE_LANGUAGE_HEADER_NAME);
     |                                        ^
  15 |         const lang = isAvailableLanguageTag(langHeader) ? langHeader : sourceLanguageTag;
  16 |         return lang;
  17 |     }
 ⨯ unhandledRejection: Error: `headers` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context

Copy link
Member

@asterikx did that happen with your patch file too?

if not, can you open a PR with the diff of your patch file?

@asterikx
Copy link
Author

asterikx commented Oct 31, 2024

@samuelstroschein I did some more trial and error, and I could get rid of the error by:

  1. Removing/commenting out the top-level call to getLanguage in the LanguageProvider (I'm not sure about its implications):
diff --git a/dist/paraglide-next/src/app/providers/LanguageProvider.js b/dist/paraglide-next/src/app/providers/LanguageProvider.js
index 16cd65d717b250ec9644b5057b810f48cad0157d..dda9b90cbceb94ce909ca0f640a9d9315fd0f21c 100644
--- a/dist/paraglide-next/src/app/providers/LanguageProvider.js
+++ b/dist/paraglide-next/src/app/providers/LanguageProvider.js
@@ -3,9 +3,9 @@ import { setLanguageTag, languageTag } from '$paraglide/runtime.js';
 import { ClientLanguageProvider } from './ClientLanguageProvider.js';
 import { getLanguage } from '../getLanguage.server.js';
 
-(async () => {
-    setLanguageTag(await getLanguage());
-})();
+// (async () => {
+//     setLanguageTag(await getLanguage());
+// })();
 //If we can reliably call setLanguageTag() from middleware.tsx, we can probably get rid of this component
 async function LanguageProvider(props) {
     setLanguageTag(await getLanguage());
  1. Removing any calls to initializeLanguage in server actions as described in the docs here: https://inlang.com/m/osslbuzt/paraglide-next-i18n/advanced/usage-on-the-server.
    However, this forces me to pass the user's locale in any call to m functions, i.e. m.welcomeMessage(undefined, { languageTag: 'de-DE' }).

I'm curious, if there is a better way to handle server actions. Possibly need to call initializeLanguage in server action bodies instead of calling it top-level.

@samuelstroschein If you think it's okay to remove the top-level call to getLanguage in the LanguageProvider, I can open a PR for that.

@tylkomat
Copy link

I was just about the add a comment the moment you sent your comment @asterikx
I was just doing your nr. 1 and that looks to be enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants