next.js icon indicating copy to clipboard operation
next.js copied to clipboard

TypeError: Cannot set property Headers of #<Object> which has only a getter

Open GGAlanSmithee opened this issue 3 years ago • 4 comments

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

GGAlanSmithee avatar Oct 26 '22 16:10 GGAlanSmithee

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 avatar Oct 27 '22 07:10 yeliex

@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?

GGAlanSmithee avatar Oct 27 '22 14:10 GGAlanSmithee

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:

balazsorban44 avatar Oct 27 '22 20:10 balazsorban44

@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.

GGAlanSmithee avatar Oct 29 '22 21:10 GGAlanSmithee

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 avatar Dec 22 '22 09:12 Boniqx

@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:

  1. Find the offending package (seems like you think it's apollo-client)
  2. Send an issue, or PR, to them with an equal fix

That is, if the issue is the same as what I experienced

GGAlanSmithee avatar Dec 22 '22 09:12 GGAlanSmithee

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.

szilarddoro avatar Feb 24 '23 14:02 szilarddoro