-
Notifications
You must be signed in to change notification settings - Fork 62
Description
Describe the bug
Bug Description
Running opennextjs-cloudflare preview
on Windows can fail with the following error:
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
This occurs because the retrieveCompiledConfig()
function in cli/commands/utils.ts can dynamically import a local file using a raw absolute Windows path (C:\...
) rather than a proper file://
URI on the line const config = await import(configPath).then((mod) => mod.default);
.
This is potentially an issue only arising in monorepos, as I have not seen it happen elsewhere. The monorepo structure hoists @opennext/cloudflare
to the node_modules
in the project root.
This bug is also intermittent. The first time running the preview
command can run successfully.
Steps to reproduce
- Create a turbo repo:
npx create-turbo@latest
- CD into
apps
and runnpm create cloudflare@latest -- my-next-app --framework=next --platform=workers
- Run
opennextjs-cloudflare preview
- Observe the error
Expected behavior
System is able to build and run correctly
@opennextjs/cloudflare version
1.6.1
Wrangler version
4.25.1
next info output
Operating System:
Platform: win32
Arch: x64
Version: Windows 10 Pro
Available memory (MB): 65365
Available CPU cores: 16
Binaries:
Node: 22.17.0
npm: 11.4.2
Yarn: N/A
pnpm: N/A
Relevant Packages:
next: 15.3.0
eslint-config-next: N/A
react: 19.1.0
react-dom: 19.1.0
typescript: 5.8.3
Next.js Config:
output: N/A
Additional context
This can be temporarily patched for Windows users if you are running into this bug. A quick manual patch:
- Locate the
utils.ts
file located inroot\node_modules\@opennextjs\cloudflare\dist\cli\commands
- Add
import { pathToFileURL } from "url";
to the top of the file - Replace
const config = await import(configPath).then((mod) => mod.default);
withconst config = await import(pathToFileURL(configPath).href).then((mod) => mod.default);
If this patch works successfully, you can automate the patching using patch-package so that you don't have to re-do this every time you re-install dependencies (or upgrade versions).
- In your monorepo root, run
npm i patch-package --save-dev
- In your monorepo root, create the file :
patches/@opennextjs+cloudflare+1.6.1.patch
. The 1.6.1 denotes the version of the package where you must adjust accordingly, or leave as it is if you are using 1.6.1. Patches is a new folder you must create if it does not already exist. - Inside
@opennextjs+cloudflare+1.6.1.patch
file, insert the following:
diff --git a/node_modules/@opennextjs/cloudflare/dist/cli/commands/utils.js b/node_modules/@opennextjs/cloudflare/dist/cli/commands/utils.js
index 562ba80..d232437 100644
--- a/node_modules/@opennextjs/cloudflare/dist/cli/commands/utils.js
+++ b/node_modules/@opennextjs/cloudflare/dist/cli/commands/utils.js
@@ -7,6 +7,7 @@ import { printHeader, showWarningOnWindows } from "@opennextjs/aws/build/utils.j
import logger from "@opennextjs/aws/logger.js";
import { unstable_readConfig } from "wrangler";
import { createOpenNextConfigIfNotExistent, ensureCloudflareConfig } from "../build/utils/index.js";
+import { pathToFileURL } from "url";
export const nextAppDir = process.cwd();
/**
* Print headers and warnings for the CLI.
@@ -39,7 +40,8 @@ export async function retrieveCompiledConfig() {
logger.error("Could not find compiled Open Next config, did you run the build command?");
process.exit(1);
}
- const config = await import(configPath).then((mod) => mod.default);
+ // const config = await import(configPath).then((mod) => mod.default);
+ const config = await import(pathToFileURL(configPath).href).then((mod) => mod.default);
ensureCloudflareConfig(config);
return { config };
}
- Add
"postinstall": "patch-package"
to your rootpackage.json
scripts. This will automatically apply after running installs.