TypeError: Cannot set property Headers of #<Object> which has only a getter
Verify canary release
- [X] I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System: Platform: win32 Arch: x64 Version: Windows 10 Pro Binaries: Node: 16.15.0 npm: N/A Yarn: N/A pnpm: N/A Relevant packages: next: 12.3.2-canary.43 eslint-config-next: 13.0.0 react: 18.2.0 react-dom: 18.2.0
What browser are you using? (if relevant)
Brave 1.45.113
How are you deploying your application? (if relevant)
No response
Describe the Bug
When upgrading to next.js 12 -> 13 (everything else being equal) I am getting an error that I did not before:
TypeError: Cannot set property Headers of #<Object> which has only a getter
I've tracked this to a third-party package, and to a line that modifies the global object in a way that does not seem to be permitted: https://github.com/spacebudz/lucid/blob/main/src/core/core.ts#L19
Looking at this, https://nodejs.org/api/globals.html#class-headers, it seems that there is a Headers object on the global nodejs environment since node.js >= 16.15.0, so the error might be legit, if the Headers object is read-only, but if so, why am I only seeing this issue with the latest version of next.js? (again, everything else being equal, also cannot reproduce this in an isolated node.js project with same node version)
Expected Behavior
For the application to work as with next.js 12
Link to reproduction
https://github.com/GGAlanSmithee/nextjs-13-cardano-lucid-repro
To Reproduce
Simply run the app and visit http://localhost:3000.
PS. the next.config file was modified to allow for top level awaits, if that affects anything
https://github.com/vercel/next.js/commit/e0cc9cd44ffd11fa7b446ffe7f25a35fca8f66f3
Nextjs has upgraded the fetch polyfill to undici under node@18, this keeps the same behavior as node.js
@yeliex ok thanks, I guess this indicates that the package is at fault, with the monkey patching of the Headers object, even though it didn't break previously?
Node.js 18 is not polyfilled at all, as it already has fetch available.
https://github.com/vercel/next.js/blob/227c35c0e281b38ff4f36b590624ffb802f5a8c7/packages/next/server/node-polyfill-fetch.js#L3
Further, the enableUndici option must be explicitly set for the new behavior so I am not sure it is related. :thinking:
@yeliex @balazsorban44
I submitted a PR to the offending package, https://github.com/spacebudz/lucid/pull/108, that conditionally polyfills these APIs, much like you do, and now everything works, so I think this is not an issue with next.js.
I will leave this issue open so you can close it as you see fit.
Thanks for the investigations.
haviong the same issue with vite I'm not sure if apollo-client is the one causing this. I'm building my own package and not really sure how to change or what to change
@Boniqx as you can see in the linked PR above, in that case, we had to add a check before polyfilling the APIs, since they are there (as readonly) in newer versions of node-js. I would guess you need to do the same:
- Find the offending package (seems like you think it's apollo-client)
- Send an issue, or PR, to them with an equal fix
That is, if the issue is the same as what I experienced
We have received reports of errors from users of our SDK after we replaced axios with cross-fetch.
This appears to be the cause of the issue: https://github.com/vercel/next.js/blob/227c35c0e281b38ff4f36b590624ffb802f5a8c7/packages/next/server/node-polyfill-fetch.js#L50-L66
Regardless of the enableUndici experimental setting, Next.js overwrites the global Headers object. Therefore, it does not seem to be connected to the transition to undici. It is unclear whether this is the responsibility of the library to address, or if Next.js should be less restrictive in this area. It is worth noting that this issue does not arise when using Node 18.x because that part of the code is not executed because fetch is globally available.