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

Doesn't work when a page.tsx throws an unhandled exception. #106

Open
carlos-dubon opened this issue Feb 10, 2024 · 12 comments
Open

Doesn't work when a page.tsx throws an unhandled exception. #106

carlos-dubon opened this issue Feb 10, 2024 · 12 comments
Assignees
Labels
bug Something isn't working

Comments

@carlos-dubon
Copy link

The library stops working when a page.tsx throws an unhandled error. This results in a cascade of issues in my app.

Expected behaviour: read env vars even tho there is an unhandled exception in a page/layout..

// app/page.tsx
import { env } from 'next-runtime-env';
const NETWORKING_ENVIRONMENT = env('NEXT_PUBLIC_NETWORKING_ENVIRONMENT')

async function getData(): Promise<number> {
    throw new Error('This is a test error');
    return 1;
}

export default async function Home() {
    const pageData = await getData();

    return (
       <div>
home page
<div>ENV: {NETWORKING_ENVIRONMENT}</div> This stops reading/working...
</div>
    );
}
@ccxdev
Copy link

ccxdev commented Feb 23, 2024

I think I have similar issue. When navigating to non-existing page.

NextJS throw error:

Failed prop type: The prop href expects a string or object in <Link>, but got undefined instead.`

Because of appUrl and window['__ENV'] are undefined.

# .env

NEXT_PUBLIC_APP_URL=http://localhost:3000
// config.ts

import { env } from "next-runtime-env"

export const appUrl = env("NEXT_PUBLIC_APP_URL")
// not-found.tsx

'use client'

import Link from "next/link"
import { appUrl } from "./config.ts"

export default function NotFound() {
  console.log(window['__ENV']) // undefined
  console.log(appUrl) // undefined


  return <Link href={appUrl}>Back home</Link>
}

@carlos-dubon
Copy link
Author

@nekotoriy I found a workaround, and it is using the provider aproach: https://github.com/expatfile/next-runtime-env/tree/main/examples/with-app-router-context This works for my use case.

NOTE: This is NOT a solution, so please don't close the issue!!

@HofmannZ HofmannZ added the bug Something isn't working label Mar 26, 2024
@HofmannZ
Copy link
Member

Thanks for reporting this issue.

@carlos-dubon the env utility in the server is just a wrapper around process.env[key]. Can you confirm that `process.env.NEXT_PUBLIC_NETWORKING_ENVIRONMENT' does provide the correct variable in the server component.

@nekotoriy - I don't think this issue is related, as you are using the env utility in a client component. The question here is if Next.js wraps the not found page with the root layout which would expose the environment variables in the client.

@emreakdas
Copy link

emreakdas commented Mar 26, 2024

@HofmannZ

 Error: Environment variable 'blablabla' is not public and cannot be accessed in the browser

I'm getting an error.

<PublicEnvScript />

installation.

@HofmannZ
Copy link
Member

HofmannZ commented Apr 1, 2024

@emreakdas - Can you please provide some additional context?

@emreakdas
Copy link

@HofmannZ NextJS 14

I use it normally with this usage, there is nothing extra I do, but it gives the above error in the console

// app/layout.tsx
import { PublicEnvScript } from 'next-runtime-env';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <PublicEnvScript />
      </head>
      <body>
        {children}
      </body>
    </html>
  );
}

@gregorybolkenstijn
Copy link

@HofmannZ NextJS 14

I use it normally with this usage, there is nothing extra I do, but it gives the above error in the console

// app/layout.tsx
import { PublicEnvScript } from 'next-runtime-env';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <PublicEnvScript />
      </head>
      <body>
        {children}
      </body>
    </html>
  );
}

The env vars stop working once it hits a 404 page, a not-found.tsx in the root of the app directory. The root layout has the <PublicEnvScript /> component and is rendered, but window.__ENV is empty.

@emreakdas
Copy link

@HofmannZ NextJS 14
I use it normally with this usage, there is nothing extra I do, but it gives the above error in the console

// app/layout.tsx
import { PublicEnvScript } from 'next-runtime-env';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <PublicEnvScript />
      </head>
      <body>
        {children}
      </body>
    </html>
  );
}

The env vars stop working once it hits a 404 page, a not-found.tsx in the root of the app directory. The root layout has the <PublicEnvScript /> component and is rendered, but window.__ENV is empty.

unfortunately I have given up using this package, but what is the solution? isn't this a package problem?

@HofmannZ
Copy link
Member

HofmannZ commented Apr 2, 2024

@HofmannZ NextJS 14
I use it normally with this usage, there is nothing extra I do, but it gives the above error in the console

// app/layout.tsx
import { PublicEnvScript } from 'next-runtime-env';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <PublicEnvScript />
      </head>
      <body>
        {children}
      </body>
    </html>
  );
}

The env vars stop working once it hits a 404 page, a not-found.tsx in the root of the app directory. The root layout has the <PublicEnvScript /> component and is rendered, but window.__ENV is empty.

@gregorybolkenstijn I will add an example to try and replicate.

@HofmannZ HofmannZ self-assigned this Apr 2, 2024
@HofmannZ
Copy link
Member

HofmannZ commented Apr 2, 2024

I was able to replicate the initial issue reported by @carlos-dubon. The problem appears to be that Next.js does not include the scripts from the top-level layout when a server error occurs. I attempted to address this by adding an error.tsx file to handle the error, but it didn't have any impact. I also tried switching from an HTML script tag to using Script from next/script, but the result was the same.

This seems to be a problem with Next.js itself, rather than with our package, and I've opened an issue on their GitHub repository. If you'd like to keep track of its progress, please give it an upvote: vercel/next.js#63980

However, I did confirm that everything works fine on the not-found page. (@gregorybolkenstijn, I can't reproduce your issue.)

@gregorybolkenstijn
Copy link

This comment in the. related Next.js issue gave us an idea of how to tackle this issue: vercel/next.js#63980 (comment)

The solution of adding a loading.tsx fixed it, but it also led to an unnecessary and intrusive loading state between pages. This other remark led us to another solution though:

If an error occurs on the server, react will skip SSR up to the nearest suspense boundary

So we wrapped the children in a <Suspense> in the root layout to allow that component to be partially rendered on the server correctly:

// app/layout.tsx
import { PublicEnvScript } from 'next-runtime-env';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <PublicEnvScript />
      </head>
      <body>
        <Suspense>{children}</Suspense>
      </body>
    </html>
  );
}

It has worked well for us, we have not experienced any issues.

@lightrow
Copy link

lightrow commented May 13, 2024

This comment in the. related Next.js issue gave us an idea of how to tackle this issue: vercel/next.js#63980 (comment)

The solution of adding a loading.tsx fixed it, but it also led to an unnecessary and intrusive loading state between pages. This other remark led us to another solution though:

If an error occurs on the server, react will skip SSR up to the nearest suspense boundary

So we wrapped the children in a <Suspense> in the root layout to allow that component to be partially rendered on the server correctly:

// app/layout.tsx
import { PublicEnvScript } from 'next-runtime-env';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <PublicEnvScript />
      </head>
      <body>
        <Suspense>{children}</Suspense>
      </body>
    </html>
  );
}

It has worked well for us, we have not experienced any issues.

that's bad for UX though, user just sees a blank page until everything is loaded.

A better solution is to set up an /error/page.tsx and /not-found/page.tsx and redirect to those pages on 500 or 404, that way the scripts will load.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

6 participants