Repository navigation
Description
I wanted to discuss regarding devs filing issues and complain about undici not working in node 18.
First of all to the devs, with issues in node 18:
Maybe you can not upgrade to node 20+, for various reasons. We dont judge you.
You can mitigate the issue by writing a simple wrapper.
In cjs:
undici-wrapper.cjs:
'use strict';
const { toUSVString } = require('util')
const { Blob, File } = require('buffer');
if (typeof globalThis.Blob === 'undefined') {
globalThis.Blob = Blob;
}
if (typeof globalThis.File === 'undefined') {
globalThis.File = File;
}
if (String.prototype.toWellFormed === undefined) {
String.prototype.toWellFormed = function () {
return toUSVString(this);
}
}
if (String.prototype.isWellFormed === undefined) {
String.prototype.isWellFormed = function () {
return toUSVString(this) === this;
}
}
const undici = require('undici');
module.exports = undici;fetch.cjs:
'use strict';
const { fetch } = require('./undici-wrapper.cjs');
async function run () {
const response = await fetch('https://google.com')
await response.blob()
}
run()similar esm:
undici-wrapper.mjs
import { toUSVString } from 'util';
import { Blob, File } from 'buffer';
if (typeof globalThis.Blob === 'undefined') {
globalThis.Blob = Blob;
}
if (typeof globalThis.File === 'undefined') {
globalThis.File = File;
}
if (String.prototype.toWellFormed === undefined) {
String.prototype.toWellFormed = function () {
return toUSVString(this);
}
}
if (String.prototype.isWellFormed === undefined) {
String.prototype.isWellFormed = function () {
return toUSVString(this) === this;
}
}
const undici = await import('undici');
export default undici;fetch.mjs
import undici from './undici-wrapper.mjs';
const { fetch } = undici;
const response = await fetch('https://google.com')
await response.blob()I tested it locally and it worked accordingly. You can of course modify it to your needs, for example by explicitly exporting fetch so that you can make a named import. I think you get the gist of it.
As you can see... we modify the prototype of String! This will result in performance degredation!
I actually wonder why nobody reported a breaking change, as node 18 does not have isWellFormed or toWellFormed on the String.prototype.
So assess the options: upgrade node and use latest undici or stick with the version of undici which works for you.
But you should have now the tools to continue your work.
Regarding the clarity:
Undici does not support node 18 since version 7.0.0. In the release notes to v7 on github, it is not clear for the "regular" dev. We just have a PR for dropping node 18 from the ci pipeline. For a regular dev, it is not clear, that we stop supporting node 18.
See https://github.com/nodejs/undici/releases/tag/v7.0.0
We should maybe consider to put it more dominant at the top of the release notes. We can still modify the v7 release notes and explicityl state that we dropped v18 support. For undici v8, we should make it more clear listing the breaking changes in the top of the release notes.
Also we should consider putting a section in the readme.md, clarifying which node versions we support.
Activity
[-]Using latest undici with node 18[/-][+]Regarding issues using latest/v7.13.0 undici with node 18[/+]joejonespushsecurity commentedon Jul 31, 2025
Just my 2 cents here.
For the table in the
Long Term Supportsection that talks about the lib version and the node version isn't very clear. At least to me it isn't. With 7.12.0 working with the version of node 18 that I was using. Whereas based on the table I wouldn't have expected 6.x to work with 18 nevermind 7.x. This might be because we're not using certain code paths or something 🤷♂️Also I'd sort of expect the none of version 7.x to work with node 18 but up to 7.12.0 it did.
In my use case undici is only installed as a dependency of a CLI tool that I'm using auth0-deploy-cli. So I don't really have control of the version restrictions at that point. This also makes it a little more awkward to add the wrapper if I wanted to.
I also imagine that those wrappers while helpful will become outdated fairly quickly. Like the File condition wasn't needed until 7.12.0 -> 7.13.0
Sure updating to node 20 is preferable but when you're trying to get other change out it's not always an easy swap.
Uzlopak commentedon Jul 31, 2025
Yes, the section about "long term support" is confusing.
Also npm i should throw an expectations not met error/warning because of the engines field explicitly set.
undici/package.json
Line 133 in 8bbf77c
But i guess that doesnt show up, when dependabot/renovate updates the dependency by directly modifying the lock file?!
This wrapper is of course not complete or well tested. But it would be not a biggie to test. E.g. clone this repo, install deps, put the polyfills on top of the bundled file, and run the tests. I guess you will get issues with the FinalizationRegistry. If somebody was using 7.12.0, than those issues were anyway existing. So better than nothing?
ci: Upgrade node version to avoid undici error
Uzlopak commentedon Aug 2, 2025
If you have the issue that undici is a transient dependency:
You could use the overrides configuration option in package.json to force npm to load a specific versions for transient dependencies.
You could pin the undici version to 7.12.0. You could also resolve undici to a local file, for example to the suggested wrapper.
Uzlopak commentedon Aug 7, 2025
No, the "issue" is that node18 had not Blob and File available in globalThis. From node 20 and newer Blob and File are globally available. We just removed the require calls from the node native buffer module, because we just support node 20+.
The issue is that people use node 18, Despite that we dont Support it.
Inject global `File` and `Blob` when running jest on Node.js 18