{"record":{"id":"7e0504c7574cadab","repo":"nodejs/node","slug":"argument-agent-must-implement-agent","errorCode":null,"errorMessage":"Argument agent must implement Agent","messagePattern":"Argument agent must implement Agent","errorType":"exception","errorClass":"InvalidArgumentError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/global.js","lineNumber":20,"sourceCode":"\n// We include a version number for the Dispatcher API. In case of breaking changes,\n// this version number must be increased to avoid conflicts.\nconst globalDispatcher = Symbol.for('undici.globalDispatcher.2')\nconst legacyGlobalDispatcher = Symbol.for('undici.globalDispatcher.1')\nconst { InvalidArgumentError } = require('./core/errors')\nconst Agent = require('./dispatcher/agent')\nconst Dispatcher1Wrapper = require('./dispatcher/dispatcher1-wrapper')\n\n// Fallback storage for when globalThis is not extensible (e.g. frozen)\nlet fallbackDispatcher\n\nif (getGlobalDispatcher() === undefined) {\n  setGlobalDispatcher(new Agent())\n}\n\nfunction setGlobalDispatcher (agent) {\n  if (!agent || typeof agent.dispatch !== 'function') {\n    throw new InvalidArgumentError('Argument agent must implement Agent')\n  }\n\n  try {\n    Object.defineProperty(globalThis, globalDispatcher, {\n      value: agent,\n      writable: true,\n      enumerable: false,\n      configurable: false\n    })\n  } catch (err) {\n    // globalThis is not extensible (e.g. Object.freeze(globalThis))\n    // Use fallback storage instead\n    if (err instanceof TypeError) {\n      fallbackDispatcher = agent\n      return\n    }\n    throw err\n  }","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/global.js#L2-L38","documentation":"Thrown by setGlobalDispatcher when the supplied agent is falsy or lacks a dispatch function. The global dispatcher must satisfy the Dispatcher contract (duck-typed on dispatch), because undici's global APIs (fetch, request, etc.) call agent.dispatch under the hood. The guard is !agent || typeof agent.dispatch !== 'function'.","triggerScenarios":"Calling setGlobalDispatcher(undefined), setGlobalDispatcher(null), or passing a plain object/class instance that does not expose dispatch. Also hit by passing an Agent-like wrapper that forgot to forward dispatch.","commonSituations":"Test teardown that resets the global dispatcher to undefined; constructing a custom Dispatcher class without a dispatch method; passing a config object instead of an Agent; partial mock that omits dispatch.","solutions":["Pass an Agent instance or any object exposing a dispatch(opts, handler) function.","To reset to the default, call setGlobalDispatcher(new Agent()) rather than undefined.","Ensure custom Dispatcher subclasses implement dispatch.","In tests, restore the previously captured global dispatcher instead of clearing it."],"exampleFix":"// before\nsetGlobalDispatcher(undefined)\n// after\nconst { Agent, setGlobalDispatcher } = require('undici')\nsetGlobalDispatcher(new Agent({ connections: 10 }))","handlingStrategy":"type-guard","validationCode":"function ensureDispatcher(agent) {\n  if (!agent || typeof agent.dispatch !== 'function') {\n    throw new TypeError('agent must implement dispatch')\n  }\n  return agent\n}\nsetGlobalDispatcher(ensureDispatcher(agent))","typeGuard":"function isDispatcher(agent) {\n  return agent != null && typeof agent.dispatch === 'function'\n}","tryCatchPattern":null,"preventionTips":["Reset to a fresh Agent, never to undefined.","Ensure custom Dispatcher subclasses implement dispatch.","In tests, capture and restore the prior global dispatcher."],"tags":["undici","global","dispatcher","invalid-arg"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}