nodejs/node · error · InvalidArgumentError

factory must be a function.

Error message

factory must be a function.

What it means

Thrown by the RoundRobinPool constructor when factory is not a function. RoundRobinPool relies on factory to instantiate each client it load-balances across; a non-callable factory cannot build clients. The guard matches Pool's: typeof factory !== 'function'.

Source

Thrown at deps/undici/src/lib/dispatcher/round-robin-pool.js:49

    connections,
    factory = defaultFactory,
    connect,
    connectTimeout,
    tls,
    maxCachedSessions,
    socketPath,
    autoSelectFamily,
    autoSelectFamilyAttemptTimeout,
    allowH2,
    clientTtl,
    ...options
  } = {}) {
    if (connections != null && (!Number.isFinite(connections) || connections < 0)) {
      throw new InvalidArgumentError('invalid connections')
    }

    if (typeof factory !== 'function') {
      throw new InvalidArgumentError('factory must be a function.')
    }

    if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') {
      throw new InvalidArgumentError('connect must be a function or an object')
    }

    if (typeof connect !== 'function') {
      connect = buildConnector({
        ...tls,
        maxCachedSessions,
        allowH2,
        socketPath,
        timeout: connectTimeout,
        ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
        ...connect
      })
    }

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Pass the class/function reference: factory: (origin, opts) => new Client(origin, opts), or omit it for the default.
  2. Do not pass a pre-built instance as factory.
  3. Keep factory assignment in code, not in deserialized config.
  4. If you only need custom sockets, set connect instead.

Example fix

// before
new RoundRobinPool(url, { factory: new Client(url) })
// after
new RoundRobinPool(url, { factory: (origin, opts) => new Client(origin, opts) })
Defensive patterns

Strategy: type-guard

Validate before calling

if (cfg.factory != null && typeof cfg.factory !== 'function') {
  throw new TypeError('factory must be a function/class reference, not an instance')
}
new RoundRobinPool(url, { factory: cfg.factory })

Type guard

function isFactory(v) { return v == null || typeof v === 'function' }

Prevention

When it happens

Trigger: Passing factory as an object, string, or an already-constructed client instance. RoundRobinPool calls factory(origin, opts) per connection, so it needs the constructor reference, not a product.

Common situations: Passing new Client(url) (instance) instead of Client (class); importing the wrong symbol; JSON config that cannot carry functions; refactoring that wrapped the factory in an options bag.

Related errors


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