nodejs/node · error · InvalidArgumentError
UND_ERR_INVALID_ARG
UND_ERR_INVALID_ARG
Error message
invalid opts
What it means
Thrown by undici's UpgradeHandler constructor (the upgrade() / client.upgrade() API) when the first argument opts is falsy or not an object. upgrade() requires an options object describing the target host/path to tunnel to; it does not accept a bare URL string.
Source
Thrown at deps/undici/src/lib/api/api-upgrade.js:13
'use strict'
const { InvalidArgumentError, SocketError } = require('../core/errors')
const { AsyncResource } = require('node:async_hooks')
const assert = require('node:assert')
const util = require('../core/util')
const { kHTTP2Stream } = require('../core/symbols')
const { addSignal, removeSignal } = require('./abort-signal')
class UpgradeHandler extends AsyncResource {
constructor (opts, callback) {
if (!opts || typeof opts !== 'object') {
throw new InvalidArgumentError('invalid opts')
}
if (typeof callback !== 'function') {
throw new InvalidArgumentError('invalid callback')
}
const { signal, opaque, responseHeaders } = opts
if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') {
throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget')
}
super('UNDICI_UPGRADE')
this.responseHeaders = responseHeaders || null
this.opaque = opaque || null
this.callback = callback
this.abort = nullView on GitHub (pinned to 1b2de5e052)
Solutions
- Pass an options object: client.upgrade({ host, port, path, headers }).
- Build opts from a URL: const u = new URL(target); client.upgrade({ host: u.hostname, port: u.port, path: u.pathname }).
- Ensure the options bag is never conditionally undefined.
Example fix
// before
client.upgrade('example.com:443')
// after
client.upgrade({ host: 'example.com', port: 443, path: '/' }) Defensive patterns
Strategy: validation
Validate before calling
function upgradeOpts(urlOrOpts) {
if (urlOrOpts instanceof URL) return { host: urlOrOpts.hostname, port: urlOrOpts.port, path: urlOrOpts.pathname }
if (urlOrOpts && typeof urlOrOpts === 'object') return urlOrOpts
throw new TypeError('upgrade opts must be an object')
}
// client.upgrade(upgradeOpts(target), cb) Type guard
function isUpgradeOpts(v) { return !!v && typeof v === 'object' && !Array.isArray(v) } Prevention
- upgrade() takes an options object, not a URL string — unlike request().
- Build opts from a URL via new URL() and read hostname/port/path.
- Ensure the opts bag is never undefined from conditional construction.
When it happens
Trigger: Calling client.upgrade('host:443') or client.upgrade(null); passing a URL object without wrapping it in an options bag.
Common situations: Assuming upgrade() shares request()'s string-URL overload; destructuring that produced undefined; migrating from http.request upgrade code that used a string.
Related errors
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/2ac16aeebcc9f016.
Report an issue: GitHub.