Skip to content

[BUG] Error: Invariant: renderHTML should not be called in minimal mode #333

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

Closed
verdverm opened this issue Feb 4, 2025 · 44 comments · Fixed by #520
Closed

[BUG] Error: Invariant: renderHTML should not be called in minimal mode #333

verdverm opened this issue Feb 4, 2025 · 44 comments · Fixed by #520
Assignees
Labels
bug Something isn't working

Comments

@verdverm
Copy link

verdverm commented Feb 4, 2025

Describe the bug

I'm trying to make a post to the following NextJS API route and get this error back after the wrangler / opennext build. Not sure what's causing it

import { NextRequest, NextResponse } from 'next/server';
import { isValidHandle } from '@atproto/syntax'

import { client as atprotoOauthClient } from '@/lib/atproto/oauth/client'

type Session = { did: string }

export async function POST(req: NextRequest) {
  const data = await req.json()

  // Validate
  const handle = data.handle
  if (typeof handle !== 'string' || !isValidHandle(handle)) {
    return NextResponse.json({error: "invalid handle"})
  }

  // Initiate the OAuth flow
  try {
    const url = await atprotoOauthClient.authorize(handle, {
      scope: 'atproto transition:generic',
    })
    return NextResponse.json({ redirect: url.toString() })
  } catch (err) {
    return NextResponse.json({error: "oauth authorize failed", details: err, message: err.message})
  }
}

Steps to reproduce

Not sure yet, can get CF trace details

I can see about producing a minimal reproducer in the next couple of days

Expected behavior

I can post to oauth endpoint and not get errors

@opennextjs/cloudflare version

0.5.3

Wrangler version

3.109.2

next info output

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 24.3.0: Thu Jan  2 20:23:36 PST 2025; root:xnu-11215.81.4~3/RELEASE_ARM64_T8112
  Available memory (MB): 24576
  Available CPU cores: 8
Binaries:
  Node: 21.7.1
  npm: 10.5.0
  Yarn: 1.22.21
  pnpm: 8.14.0
Relevant Packages:
  next: 15.1.7 // Latest available version is detected (15.1.7).
  eslint-config-next: 15.1.0
  react: 19.0.0
  react-dom: 19.0.0
  typescript: 5.7.3
Next.js Config:
  output: standalone

Additional context

running site is at https://verdverm.verdverm.workers.dev

@verdverm verdverm added bug Something isn't working triage labels Feb 4, 2025
@verdverm
Copy link
Author

verdverm commented Feb 4, 2025

hmm, have a feeling it might be dotenv, I think I saw an error at some earlier point in previous versions of the code about fs.readFile not being implemented yet...

either way the error message coming out doesn't help me to RCA this. I did notice other endpoints which import the atprotoOauthClient (which imports dotenv) are also throwing 500 errors with the same error message


edit, dotenv does not seem to be the issue, removed it and still getting the same 500 & error message

edit2, I've done a bunch of edits to simplify things, still seeing the same error out of what I suspect is the ATProto package(s), I wonder if they are using some unsupported node:* package and the error is not bubbling up, or if it is the build process of these things causing the issue, or if the renderHtml is really about rendering the 500 page by next when it shouldn't?

@verdverm
Copy link
Author

verdverm commented Feb 4, 2025

linking in #57

@verdverm
Copy link
Author

verdverm commented Feb 4, 2025

refactored more code, per issue 57

You can not use process.env at top level

still seeing the same issue. Wondering if it is similar to NextAuth because we are doing OAuth with this package: https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client-node

@gethassaan
Copy link

gethassaan commented Feb 5, 2025

I am also facing the same issue and I am not even using 0Auth

@verdverm
Copy link
Author

verdverm commented Feb 5, 2025

@vicb

Here is a minimal reproducer: https://github.com/verdverm/cf-repro

@vicb
Copy link
Contributor

vicb commented Feb 5, 2025

Thanks,
This issue is on my radar as it makes debugging errors cumbersome.
I'll probably start investigating early next week.

@verdverm
Copy link
Author

verdverm commented Feb 5, 2025

thanks, keep me posted, I have one more thing I want to try (a hacky shim for one of the packages I'm using for ATProto)

It certainly seems like this renderHTML is not the real error, as you say, hard to debug. Will be great to see more relevance in the CF logs

@verdverm
Copy link
Author

verdverm commented Feb 6, 2025

Some additional context, issues, and workarounds w.r.t. ATproto OAuth on Cloudflare Workers

bluesky-social/atproto#3292

@wesbos
Copy link
Contributor

wesbos commented Feb 7, 2025

Was also hitting this and I finally narrowed it down to a not-found.tsx that tried to access headers:

import { headers } from 'next/headers';

export default async function NotFound() {
  const headersList = await headers();
  console.log(headersList);
  return (
    <div>
      <h2>Not Found</h2>
      <p>Could not find requested resource</p>
    </div>
  );
}

This code is pretty much straight from the next.js docs for creating a not found page. It's the getHeaders() call that breaks the entire site and throws the renderHTML error

@verdverm
Copy link
Author

verdverm commented Feb 7, 2025

My not found is much simpler, has always been this, including with my error above

const NotFound = () => {
  return (
    <div>
    <div className="py-24 flex flex-1 w-full justify-center space-x-8">

      <span className="font-light text-gray-600 italic text-3xl pt-4">
        404 - Not Found
      </span>

    </div>
    </div>
  )
}

export default NotFound

@gethassaan
Copy link

I am getting this error when nextjs runs the API's in app/api folder.

@verdverm
Copy link
Author

@gethassaan it is almost certainly a specific library or function you are using. I have routes in app/api that work just fine.

I've also been able to make progress by removing my ORM and using the D1 bindings and handwritten SQL instead. Prisma is broken for me, as is ATProto OAuth library (i'm using passwords for now, while I wait for a fix here, which should give me a better error so I know what is actually going wrong)

@P4rthPat3l
Copy link

I created a demo application in Next.js with a simple POST API route, without using any additional libraries or packages. It runs perfectly fine during development and build time without Wrangler. However, when running in preview mode, I encounter the error mentioned in the issue title, and I'm not sure why.

Here is the project link if you'd like to take a look. I haven't removed anything, so you should be able to understand the setup. Nothing in the code is confidential.

🔗 Project Link: https://github.com/P4rthPat3l/nextjs-isr-demo

@Maxtermax
Copy link

Hello, I’m encountering the same issue. It appears that the NEXT_MINIMAL variable is unexpectedly set to true when renderHTMLImpl is called. Could you confirm if this variable is intentionally set to true during the build process?

@Maxtermax
Copy link

Looks like it's intentionally set to true

this appears to be the source of the issue. A more effective approach could be:

"process.env.NEXT_MINIMAL": process.env.NEXT_MINIMAL ?? "true",

unless "process.env.NEXT_MINIMAL": "true", is explicitly necessary for some reason.

@verdverm
Copy link
Author

@verdverm
Copy link
Author

Some more context: https://github.com/search?q=repo%3Avercel%2Fnext.js%20NEXT_MINIMAL&type=code

Looks like it largely controls how imports/requires are handled

@verdverm
Copy link
Author

verdverm commented Feb 26, 2025

I wonder if this comment from 2021 still holds true: vercel/next.js#29801 (comment)

Discovered from: vercel/next.js#75102

@vicb
Copy link
Contributor

vicb commented Feb 26, 2025

process.env.NEXT_MINIMAL is linked to minimal mode but not minimal mode (which is a parameter to the Next server).

"process.env.NEXT_MINIMAL": "true" is useful to reduce the bundle size for now. We might drop it at some point but it is not enough to solve the issue here.

@Maxtermax
Copy link

Maxtermax commented Feb 26, 2025

I checked the nextjs code i found that probably the renderHTML being called when it should not, in my case i'm trying to run this of code:

// app/api/auth/[kindeAuth]/route.ts

import {handleAuth} from "@kinde-oss/kinde-auth-nextjs/server";

export const GET = handleAuth();

locally that code works by redirecting me to the kinde login page, but due this issue the renderHTML is being called instead of the redirect, i think the real issue is that the auth/kinde module is not being recognized as a page route and is being handle as a normal page.

I'm testing my theory.

@j4tmr
Copy link

j4tmr commented Feb 27, 2025

after upgrade to nextjs 15.2.0, i faced the same error. My old project hasn't been touched for a long time; I've only updated the Next.js version. However, there are still no issues with versions 15.1.7 or 15.1.6.

@xlc
Copy link

xlc commented Feb 27, 2025

I am seeing this issue for all api requests and happens after I upgraded nextjs from 15.1.7 to 15.2.0

@justid
Copy link

justid commented Mar 1, 2025

Facing same issue here, i can confirm that next 15.1.6 doesnt have this issue

@verdverm
Copy link
Author

verdverm commented Mar 10, 2025

@vicb still seems like the real error is being hidden. I'm now seeing

✘ [ERROR] ⨯ TypeError: Cannot read properties of undefined (reading 'definition')

Though the third line on the minified stack trace looks to indicate it wants to return a string about an unsupported api usage (which is what I expect the real error to be)

I updated wrangler and opennext to the latest in my repro: https://github.com/verdverm/cf-repro

@gethassaan
Copy link

I am also facing the same issue.

@vicb
Copy link
Contributor

vicb commented Mar 11, 2025

Thanks for your feedback @verdverm, we will take a look

@vicb
Copy link
Contributor

vicb commented Mar 31, 2025

I've been looking into that a bit.

When the route "app/oauth/login/route.js" is required from function requirePage(page, distDir, isAppPath) {...}, the return value is an empty object. I need to investigate more.

(It looks like the route requires node:http, node:https, and node:http2 so it will probably not work as such on Workers)

@vicb
Copy link
Contributor

vicb commented Mar 31, 2025

@verdverm Could you please try to build your app with yarn worker:build, then add

import process from "node:process";
Object.assign(process.versions, {node: "18.0.0"});
Object.assign(process, {version : "v18"});

at the top of ./open-next/worker.js and then yarn wrangler dev or deploy.

Details:
It looks like some libs are using feature detection.

Object.assign(process.versions, {node: "18.0.0"}); is used to prevent using util.deepClone.

Object.assign(process, {version : "v18"}); is used to prevent the usage of WeakRef and FinalizationRegistry that are not supported by the Workers.

@verdverm
Copy link
Author

verdverm commented Mar 31, 2025

@vicb, I updated wrangler and opennextjs, still seeing a 500. Did confirm it still works in local dev mode

(this is using the actual application rather than the reproducer, but should be equivalent)

✘ [ERROR] ⨯ TypeError: Cannot read properties of undefined (reading 'definition')

      at aW
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:3563:1725)
      at lazyRenderAppPage
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:4556:765299)
      at ye.renderHTMLImpl
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:4571:17064)
      at <unknown>
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:4571:16774)
      at b.trace
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:2966:69329)
      at ye.renderHTML
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:4571:16722)
      at doRender
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:2997:27204)
      at responseGenerator
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:2999:2679)
      at r.get
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:2973:19276)
      at ye.renderToResponseWithComponentsImpl
  (Users/tony/blebbit/blebbit/services/webapp/.wrangler/tmp/dev-QCn88a/worker.js:2999:2819)


[wrangler:inf] POST /oauth/login 500 Internal Server Error (27ms)

The first line where the undefined definition occurs looks like

if(Ts.pathname&&!Te){let Ke=`${te.gW}${Ts.pathname}`;H.push(Ke)}return H}(hr.routeModule.definition.page,Kr,Xn),ms=function({page:Xi,fallbackRouteParams:Ts,renderOpts:N,requestEndedState:H,isPrefetchRequest:Te}){ ...

@vicb
Copy link
Contributor

vicb commented Mar 31, 2025

Is there a chance you can update the repro?

@mhart
Copy link

mhart commented Apr 1, 2025

@verdverm try adding the following to your wrangler.json:

  "define": {
    "process.version": "\"v22.14.0\"",
    "process.versions": "{ \"node\": \"22.14.0\" }"
  },

It's likely you're running into this: auth0/node-auth0#1027 (comment)

@mhart
Copy link

mhart commented Apr 1, 2025

If that doesn't work, you can debug further like this (we'll make this easier in the future):

  1. Run npx opennextjs-cloudflare build
  2. Edit .open-next/server-functions/default/handler.mjs
  3. Search for process.env.__NEXT_PRIVATE_RUNTIME_TYPE = "" and find the try/finally block it's in
  4. Add a catch handler just before the finally block, like this:
+      } catch (e) {
+        console.error(e);
+        throw e;
       } finally {
         process.env.__NEXT_PRIVATE_RUNTIME_TYPE = "";
       }
  1. Now run npx opennextjs-cloudflare preview

This time around, you should be able to see the root cause error, that's preventing this module from running correctly (which makes the routeModule undefined)

@verdverm
Copy link
Author

verdverm commented Apr 2, 2025

@vicb updated the repro repository

@mhart

  • didn't notice any change with the first suggestion
  • I noticed the new log line, but not in the failure path

still unable to see what the real underlying error is :[

(It looks like the route requires node:http, node:https, and node:http2 so it will probably not work as such on Workers)

I agree this is likely the underlying error. (based on comments here: bluesky-social/atproto#3292)

@mhart
Copy link

mhart commented Apr 2, 2025

I noticed the new log line, but not in the failure path

Can you clarify what this means? It shouldn't log anything unless there's an error

@verdverm
Copy link
Author

verdverm commented Apr 2, 2025

There were some other unrelated errors when the page or server loads (but seem to be handled gracefully elsewhere?), however when making the call with the known issue, it never reaches that part of the code (I assume, because that error print doesn't show)

@mhart
Copy link

mhart commented Apr 3, 2025

Hmmm, I'm suspicious of "seem to be handled gracefully elsewhere?" TBH. Can you expand on that? Like, what errors are we talking about?

Any error logged from that spot that I said to add the console.error() means there was an error importing a module. The code may continue to execute, but I'm not sure it would be handled gracefully – the module will be undefined (which is why you see the eventual error of Cannot read properties of undefined (reading 'definition'))

@gethassaan
Copy link

I am geeting this error whenever nextjs makes an internal api request to fetch the images from S3 bucket error: Error: [unenv] fs.readFile is not implemented yet! at createNotImplementedError

@verdverm
Copy link
Author

The errors I see are (from the cf-repro project I created)

  1. at the start (what I called "gracefully handled") 4x
⎔ Starting local server...
✘ [ERROR] ReferenceError: WeakRef is not defined

      at e.exports (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:151221:204)
      at 87292 (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:151990:262)
      at t (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:167035:20)
      at 2793 (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:151644:207)
      at t (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:167035:20)
      at 86739 (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:146634:19)
      at t (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:167035:20)
      at 6837 (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:158883:84)
      at t (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:167035:20)
      at 25155 (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:158842:48)
  1. same obfuscated error
✘ [ERROR] ⨯ TypeError: Cannot read properties of undefined (reading 'definition')

      at aW (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:249287:32)
      at lazyRenderAppPage
  (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:277873:20)
      at NextNodeServer.renderHTMLImpl
  (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:281322:60)
      at <unknown> (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:281314:111)
      at NextTracerImpl.trace
  (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:113815:22)
      at NextNodeServer.renderHTML
  (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:281314:45)
      at doRender (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:132965:37)
      at responseGenerator
  (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:133152:36)
      at ResponseCache.get
  (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:118317:22)
      at NextNodeServer.renderToResponseWithComponentsImpl
  (Users/tony/verdverm/cf-repro/.wrangler/tmp/dev-0h5H29/worker.js:133162:57)
  1. an error printed by additional code (used a different route than the one I normally do)
✘ [ERROR] ⨯ Error: [unenv] fs.readdir is not implemented yet!

@mhart
Copy link

mhart commented Apr 14, 2025

Right, so the real issue in that case is this then: cloudflare/workerd#3053

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

Successfully merging a pull request may close this issue.