cloudflare / cloudflare/workers-sdk
[wrangler] preserve_file_names keeps absolute non-JavaScript imports in the Worker bundle
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.5k
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 186
Description
### What versions & operating system are you using?
```text
System:
OS: Linux 6.18.33.2-microsoft-standard-WSL2 x86_64
Binaries:
Node: v24.13.0
pnpm: 9.15.9
Packages:
wrangler: 4.125.0
```
The relevant `preserveFileNames` branch is also unchanged on the current `main` branch as of 2026-08-21.
### Please provide a link to a minimal reproduction
https://gist.github.com/brassring/9c3f96982b386dbcda8de88be4e710d2
### Describe the Bug
When a non-JavaScript module is imported using an absolute path and `preserve_file_names` is enabled, Wrangler copies that absolute build-machine path into the generated Worker bundle and does not write the imported module into the dry-run output directory.
This was originally observed with `@opennextjs/cloudflare`, which intentionally turns external WASM imports into absolute paths before handing the bundle to Wrangler. The reproduction uses a plain text module instead, so it does not depend on OpenNext, Prisma, or WASM.
Steps to reproduce:
1. Clone the reproduction Gist.
2. Run `pnpm install`.
3. Run `pnpm repro`.
Actual result:
- `dist/index.js` contains `import message from "/absolute/build/path/message.txt"`.
- `message.txt` is not copied into `dist`.
- Wrangler exits successfully in dry-run mode even though the bundle contains a machine-local module specifier.
- In the original OpenNext/WASM case, uploading the resulting Worker failed validation with error code `10021`.
When `preserve_file_names` is set to `false`, Wrangler instead emits a hashed relative import and copies the module into `dist`.
Expected result:
Wrangler should produce a deployable module specifier while preserving the filename. If absolute module imports are intentionally unsupported with `preserve_file_names`, Wrangler should fail locally with an actionable error instead of producing a bundle that can only fail during upload.
Could you confirm which behavior is intended? I am happy to follow up with a regression test and fix once the expected path-rebasing behavior is clear.
Relevant source locations:
- Wrangler module collection: https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/src/deployment-bundle/module-collection.ts
- OpenNext external module handling: https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src/cli/build/patches/plugins/wrangler-external.ts
### Please provide any relevant error logs
```text
Total Upload: 0.23 KiB / gzip: 0.18 KiB
No bindings found.
--dry-run: exiting now.
{ absolutePathPreserved: true, moduleCopied: false }
```
Contributor guide
Research direction
Read packages/wrangler/src/deployment-bundle/module-collection.ts and run the linked Gist's pnpm repro to trace preserve_file_names handling for absolute non-JavaScript imports. Confirm the intended behavior using the dry-run output: the generated bundle should use a deployable module path and include the imported module, or fail locally with an actionable error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript, wasm
- Domain
- build-system, cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100