{"record":{"id":"f4aa8515eb46d880","repo":"nodejs/node","slug":"und-err-invalid-arg-f4aa85","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/agent.js","lineNumber":27,"sourceCode":"\nconst kOnConnect = Symbol('onConnect')\nconst kOnDisconnect = Symbol('onDisconnect')\nconst kOnConnectionError = Symbol('onConnectionError')\nconst kOnDrain = Symbol('onDrain')\nconst kFactory = Symbol('factory')\nconst kOptions = Symbol('options')\nconst kOrigins = Symbol('origins')\n\nfunction defaultFactory (origin, opts) {\n  return opts && opts.connections === 1\n    ? new Client(origin, opts)\n    : new Pool(origin, opts)\n}\n\nclass Agent extends DispatcherBase {\n  constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) {\n    if (typeof factory !== 'function') {\n      throw new InvalidArgumentError('factory must be a function.')\n    }\n\n    if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') {\n      throw new InvalidArgumentError('connect must be a function or an object')\n    }\n\n    if (typeof maxOrigins !== 'number' || Number.isNaN(maxOrigins) || maxOrigins <= 0) {\n      throw new InvalidArgumentError('maxOrigins must be a number greater than 0')\n    }\n\n    super(options)\n\n    if (connect && typeof connect !== 'function') {\n      connect = { ...connect }\n    }\n\n    this[kOptions] = { ...util.deepClone(options), maxOrigins, connect }\n    this[kFactory] = factory","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/dispatcher/agent.js#L9-L45","documentation":"Thrown by the Agent constructor. The factory option selects which Dispatcher (Client or Pool) the Agent creates per origin; the default returns a Pool (or a single-connection Client when connections === 1). Because the Agent invokes factory(origin, opts) as a function on every new origin, a non-function value cannot be called, so it is rejected at construction.","triggerScenarios":"new Agent({ factory: <not a function> }) — e.g. factory: Pool, factory: {}, factory: 'pool', or a destructured import that resolved to undefined.","commonSituations":"Passing a class reference without wrapping it (factory: Pool instead of (origin, opts) => new Pool(origin, opts)); a default import that returned undefined due to an ESM/CJS interop issue; a config object where factory was overwritten by a merge.","solutions":["Provide factory as a function: new Agent({ factory: (origin, opts) => new Pool(origin, opts) }).","If you want the default behavior, omit the factory option entirely.","Check that any imported Dispatcher class is actually defined (not undefined) before referencing it."],"exampleFix":"// before\nconst agent = new Agent({ factory: Pool })\n// after\nconst agent = new Agent({ factory: (origin, opts) => new Pool(origin, opts) })","handlingStrategy":"type-guard","validationCode":"function buildAgent(options = {}) {\n  if (options.factory !== undefined && typeof options.factory !== 'function') {\n    throw new TypeError('Agent options.factory must be a function')\n  }\n  return new Agent(options)\n}","typeGuard":"const isFactory = (f) => typeof f === 'function'","tryCatchPattern":null,"preventionTips":["Wrap class references: factory: (origin, opts) => new Pool(origin, opts).","Check imported symbols are defined before using them in factory."],"tags":["undici","agent","factory","constructor","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}