nodejs/node · error · InvalidArgumentError

UND_ERR_INVALID_ARG

UND_ERR_INVALID_ARG

Error message

factory must be a function.

What it means

Thrown by the BalancedPool constructor. The factory option chooses how each upstream Pool is built (default returns new Pool(origin, opts)). BalancedPool calls factory(origin, opts) when addUpstream runs, so it must be a function; a class reference or object cannot be invoked.

Source

Thrown at deps/undici/src/lib/dispatcher/balanced-pool.js:54

function getGreatestCommonDivisor (a, b) {
  if (a === 0) return b

  while (b !== 0) {
    const t = b
    b = a % b
    a = t
  }
  return a
}

function defaultFactory (origin, opts) {
  return new Pool(origin, opts)
}

class BalancedPool extends PoolBase {
  constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) {
    if (typeof factory !== 'function') {
      throw new InvalidArgumentError('factory must be a function.')
    }

    super()

    this[kOptions] = { ...util.deepClone(opts) }
    this[kIndex] = -1
    this[kCurrentWeight] = 0

    this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100
    this[kErrorPenalty] = this[kOptions].errorPenalty || 15

    if (!Array.isArray(upstreams)) {
      upstreams = [upstreams]
    }

    this[kFactory] = factory

    for (const upstream of upstreams) {

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Provide factory as a function returning a Dispatcher: new BalancedPool(urls, { factory: (origin, opts) => new Pool(origin, opts) }).
  2. Omit factory to use the default (which already builds a Pool per upstream).
  3. Verify the imported Pool/Client is defined before referencing it inside the factory.

Example fix

// before
const pool = new BalancedPool(['a.com', 'b.com'], { factory: Pool })
// after
const pool = new BalancedPool(['a.com', 'b.com'], { factory: (origin, opts) => new Pool(origin, opts) })
Defensive patterns

Strategy: type-guard

Validate before calling

function buildBalancedPool(upstreams, options = {}) {
  if (options.factory !== undefined && typeof options.factory !== 'function') {
    throw new TypeError('BalancedPool factory must be a function')
  }
  return new BalancedPool(upstreams, options)
}

Type guard

const isFactory = (f) => typeof f === 'function'

Prevention

When it happens

Trigger: new BalancedPool(upstreams, { factory: Pool }), new BalancedPool([], { factory: {} }), or a factory import that resolved to undefined.

Common situations: Passing the Pool class directly instead of a constructor wrapper; sharing one factory function across Agent and BalancedPool with the wrong shape; a config merge that overwrote factory.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/03836e3fdccaad78. Report an issue: GitHub.