Skip to content

[BUG] initOpenNextCloudflareForDev causes some commands to never finishΒ #923

@busybox11

Description

@busybox11

Describe the bug

When using initOpenNextCloudflareForDev in next.config.ts, running the next typegen command hangs Node - a couple of active strong handles on the Node process are preventing it from stopping like it does in Vanilla Next.

This is somewhat fixed by Next in this commit which gracefully terminates the process via .exit (just like next build) - not released in npm yet.

However, the issue is still present in other next commands (such as next info).

I have a couple thoughts to share that I believe are relevant for this issue.


Does the initOpenNextCloudflareForDev function actually needs to be called unconditionally in next.config.ts?
The following code does resolve the issue and does not cause any hanging in other commands:

if (process.env.NODE_ENV === "development") initOpenNextCloudflareForDev()

It could technically reduce the probability of an unwanted side-effect to make its way onto other parts / lifecycles / commands of Next since it would only be called on development machines.

I'm not sure if this is actually desirable as I'm not very familiar with that process - it could be useful in other contexts than next dev that I'm not aware of, which is why this is an issue rather than a PR.


Could it be possible to dereference the handles created by getCloudflareContextFromWrangler?

From what I understand and tested, it appears the active blocking handles are mostly related to miniflare workers and their implementation. All remaining Next handles are directly caused by this call.

If it is possible to prevent those handles from blocking Node altogether, it shouldn't block the Node process to behave like a regular Node process would - effectively ignoring the CF side-effect for the runtime.

I was able to confirm this by explicitly calling the returned getCloudflareContextFromWrangler(...).ctx.dispose() function after a 10s delay (next typegen reports its success after 3s in my test repo).
When dispose() completes, the process does terminates gracefully, confirming that Miniflare (initialized by Wrangler) is indeed the root cause of the hang.

This behavior was also confirmed by introducing a simple, unrelated side-effect (setTimeout(() => {}, 20000) in next.config.ts).
In this scenario, the process only exits after both the setTimeout finishes, which happens after the completion of getCloudflareContextFromWrangler(...).ctx.dispose(), confirming that the Cloudflare context actually is what's blocking the process from finishing.

I'm not entirely sure if a solution can be implemented without relying on hacky workarounds (like polling handles using the private process._getActiveHandles method) unless the underlying miniflare handles can be unref()'d by default.

I probably miss a lot of knowledge and context - hope this could still help somehow, or at least give some more context in the repo.
Not entirely sure what to expect from this issue, also hope it's not going too far nor too wrong. Sorry if it is!

Steps to reproduce

  1. Create an OpenNext CF project by following the instructions on https://opennext.js.org/cloudflare

  2. Run next typegen

  3. The command should hang on βœ“ Route types generated successfully

Expected behavior

The command should not hang.

@opennextjs/cloudflare version

1.9.1

Wrangler version

4.40.3

next info output

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 ZEN SMP PREEMPT_DYNAMIC Thu, 25 Sep 2025 17:17:10 +0000
  Available memory (MB): 32034
  Available CPU cores: 12
Binaries:
  Node: 24.5.0
  npm: 11.5.1
  Yarn: 1.22.22
  pnpm: 10.16.1
Relevant Packages:
  next: 15.5.4 // Latest available version is detected (15.5.4).
  eslint-config-next: N/A
  react: 19.1.0
  react-dom: 19.1.0
  typescript: 5.9.3
Next.js Config:
  output: N/A

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions