nodejs/node · error · InvalidArgumentError

Argument agent must implement Agent

Error message

Argument agent must implement Agent

What it means

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'.

Source

Thrown at deps/undici/src/lib/global.js:20

// We include a version number for the Dispatcher API. In case of breaking changes,
// this version number must be increased to avoid conflicts.
const globalDispatcher = Symbol.for('undici.globalDispatcher.2')
const legacyGlobalDispatcher = Symbol.for('undici.globalDispatcher.1')
const { InvalidArgumentError } = require('./core/errors')
const Agent = require('./dispatcher/agent')
const Dispatcher1Wrapper = require('./dispatcher/dispatcher1-wrapper')

// Fallback storage for when globalThis is not extensible (e.g. frozen)
let fallbackDispatcher

if (getGlobalDispatcher() === undefined) {
  setGlobalDispatcher(new Agent())
}

function setGlobalDispatcher (agent) {
  if (!agent || typeof agent.dispatch !== 'function') {
    throw new InvalidArgumentError('Argument agent must implement Agent')
  }

  try {
    Object.defineProperty(globalThis, globalDispatcher, {
      value: agent,
      writable: true,
      enumerable: false,
      configurable: false
    })
  } catch (err) {
    // globalThis is not extensible (e.g. Object.freeze(globalThis))
    // Use fallback storage instead
    if (err instanceof TypeError) {
      fallbackDispatcher = agent
      return
    }
    throw err
  }

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Pass an Agent instance or any object exposing a dispatch(opts, handler) function.
  2. To reset to the default, call setGlobalDispatcher(new Agent()) rather than undefined.
  3. Ensure custom Dispatcher subclasses implement dispatch.
  4. In tests, restore the previously captured global dispatcher instead of clearing it.

Example fix

// before
setGlobalDispatcher(undefined)
// after
const { Agent, setGlobalDispatcher } = require('undici')
setGlobalDispatcher(new Agent({ connections: 10 }))
Defensive patterns

Strategy: type-guard

Validate before calling

function ensureDispatcher(agent) {
  if (!agent || typeof agent.dispatch !== 'function') {
    throw new TypeError('agent must implement dispatch')
  }
  return agent
}
setGlobalDispatcher(ensureDispatcher(agent))

Type guard

function isDispatcher(agent) {
  return agent != null && typeof agent.dispatch === 'function'
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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