{"record":{"id":"03836e3fdccaad78","repo":"nodejs/node","slug":"und-err-invalid-arg-03836e","errorCode":"UND_ERR_INVALID_ARG","errorMessage":"factory must be a function.","messagePattern":"factory must be a function\\.","errorType":"validation","errorClass":"InvalidArgumentError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/dispatcher/balanced-pool.js","lineNumber":54,"sourceCode":"function getGreatestCommonDivisor (a, b) {\n  if (a === 0) return b\n\n  while (b !== 0) {\n    const t = b\n    b = a % b\n    a = t\n  }\n  return a\n}\n\nfunction defaultFactory (origin, opts) {\n  return new Pool(origin, opts)\n}\n\nclass BalancedPool extends PoolBase {\n  constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) {\n    if (typeof factory !== 'function') {\n      throw new InvalidArgumentError('factory must be a function.')\n    }\n\n    super()\n\n    this[kOptions] = { ...util.deepClone(opts) }\n    this[kIndex] = -1\n    this[kCurrentWeight] = 0\n\n    this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100\n    this[kErrorPenalty] = this[kOptions].errorPenalty || 15\n\n    if (!Array.isArray(upstreams)) {\n      upstreams = [upstreams]\n    }\n\n    this[kFactory] = factory\n\n    for (const upstream of upstreams) {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/dispatcher/balanced-pool.js#L36-L72","documentation":"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.","triggerScenarios":"new BalancedPool(upstreams, { factory: Pool }), new BalancedPool([], { factory: {} }), or a factory import that resolved to undefined.","commonSituations":"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.","solutions":["Provide factory as a function returning a Dispatcher: new BalancedPool(urls, { factory: (origin, opts) => new Pool(origin, opts) }).","Omit factory to use the default (which already builds a Pool per upstream).","Verify the imported Pool/Client is defined before referencing it inside the factory."],"exampleFix":"// before\nconst pool = new BalancedPool(['a.com', 'b.com'], { factory: Pool })\n// after\nconst pool = new BalancedPool(['a.com', 'b.com'], { factory: (origin, opts) => new Pool(origin, opts) })","handlingStrategy":"type-guard","validationCode":"function buildBalancedPool(upstreams, options = {}) {\n  if (options.factory !== undefined && typeof options.factory !== 'function') {\n    throw new TypeError('BalancedPool factory must be a function')\n  }\n  return new BalancedPool(upstreams, options)\n}","typeGuard":"const isFactory = (f) => typeof f === 'function'","tryCatchPattern":null,"preventionTips":["Pass factory as a function returning a Pool/Client, not the class itself.","Omit factory to use the default Pool-creating implementation."],"tags":["undici","balanced-pool","factory","constructor","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}