nodejs/node · error · InvalidArgumentError
UND_ERR_INVALID_ARG
UND_ERR_INVALID_ARG
Error message
Argument opts.agent must implement Agent
What it means
Thrown by the `MockAgent` constructor (`InvalidArgumentError`, code `UND_ERR_INVALID_ARG`) when `opts.agent` is provided but does not expose a `dispatch` function. `MockAgent` wraps a real dispatcher (defaulting to a new `Agent`) and routes intercepted dispatches through it for non-mocked origins; it probes the supplied object for `dispatch` to confirm it is a Dispatcher-compatible agent. Anything lacking that method cannot be delegated to.
Source
Thrown at deps/undici/src/lib/mock/mock-agent.js:45
const Dispatcher = require('../dispatcher/dispatcher')
const PendingInterceptorsFormatter = require('./pending-interceptors-formatter')
const { MockCallHistory } = require('./mock-call-history')
class MockAgent extends Dispatcher {
constructor (opts = {}) {
super(opts)
const mockOptions = buildAndValidateMockOptions(opts)
this[kNetConnect] = true
this[kIsMockActive] = true
this[kMockAgentIsCallHistoryEnabled] = mockOptions.enableCallHistory ?? false
this[kMockAgentAcceptsNonStandardSearchParameters] = mockOptions.acceptNonStandardSearchParameters ?? false
this[kIgnoreTrailingSlash] = mockOptions.ignoreTrailingSlash ?? false
// Instantiate Agent and encapsulate
if (opts?.agent && typeof opts.agent.dispatch !== 'function') {
throw new InvalidArgumentError('Argument opts.agent must implement Agent')
}
const agent = opts?.agent ? opts.agent : new Agent(opts)
this[kAgent] = agent
this[kClients] = agent[kClients]
this[kOptions] = mockOptions
if (this[kMockAgentIsCallHistoryEnabled]) {
this[kMockAgentRegisterCallHistory]()
}
}
get (origin) {
// Normalize origin to handle URL objects and case-insensitive hostnames
const normalizedOrigin = normalizeOrigin(origin)
const originKey = this[kIgnoreTrailingSlash] ? normalizedOrigin.replace(/\/$/, '') : normalizedOrigin
let dispatcher = this[kMockAgentGet](originKey)View on GitHub (pinned to 1b2de5e052)
Solutions
- Pass an actual undici `Agent` (or any object exposing `dispatch(opts, handler)`), e.g. `new MockAgent({ agent: existingAgent })`.
- If you only want to configure the underlying agent, pass those options directly to `MockAgent` and let it construct the inner `Agent` itself.
- For custom dispatchers, ensure they expose a `dispatch` method matching the Dispatcher contract.
Example fix
// before
const agent = new MockAgent({ agent: { connections: 10 } })
const agent = new MockAgent({ agent: somePool }) // no dispatch
// after
const agent = new MockAgent({ agent: new Agent({ connections: 10 }) })
// or let MockAgent build it:
const agent = new MockAgent({ connections: 10 }) Defensive patterns
Strategy: type-guard
Validate before calling
function resolveAgent(candidate) {
if (candidate == null) return undefined
if (typeof candidate.dispatch !== 'function') {
throw new Error('opts.agent must expose a dispatch(opts, handler) function')
}
return candidate
} Type guard
function isDispatcherLike(v) {
return v != null && typeof v.dispatch === 'function'
} Prevention
- Pass an Agent instance, not an options object.
- Let MockAgent build the inner agent when you only need to configure it.
- Duck-type on dispatch, not instanceof, for custom dispatchers.
When it happens
Trigger: Passing `agent: new URL(...)`, an options object, a plain `{ connections: 10 }` (the opts, not an agent), or a custom object that forgot to implement `dispatch`. The guard is `opts?.agent && typeof opts.agent.dispatch !== 'function'`. Note the check is duck-typed on the `dispatch` method, not on `instanceof Agent`.
Common situations: Passing the agent options object where the agent instance belongs; wrapping a custom Dispatcher subclass that did not expose `dispatch`; passing a Proxy agent or Pool where the consumer expected an Agent; copy-paste from examples that use a different variable name.
Related errors
- UND_ERR_INVALID_ARG
- UND_ERR_INVALID_ARG
- expected opts.methods to be an array, got ${typeof methods}
- expected opts.skipHeaderNames to be an array, got ${typeof s
- expected opts.excludeHeaderNames to be an array, got ${typeo
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/4c1eda77d384f48c.
Report an issue: GitHub.