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 = null

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Pass an options object: client.upgrade({ host, port, path, headers }).
  2. Build opts from a URL: const u = new URL(target); client.upgrade({ host: u.hostname, port: u.port, path: u.pathname }).
  3. 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

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.