nodejs/node · error · ClientDestroyedError
UND_ERR_DESTROYED
UND_ERR_DESTROYED
Error message
The client is destroyed
What it means
ClientDestroyedError (UND_ERR_DESTROYED) thrown by dispatch() when the client/dispatcher has been destroyed (or destruction is in progress, signalled by kOnDestroyed being populated). Once destroyed, the instance rejects all new dispatches. If the handler implements onResponseError, the error is delivered there instead of thrown.
Source
Thrown at deps/undici/src/lib/dispatcher/dispatcher-base.js:165
.then(() => queueMicrotask(onDestroyed))
}
dispatch (opts, handler) {
if (!handler || typeof handler !== 'object') {
throw new InvalidArgumentError('handler must be an object')
}
try {
if (!opts || typeof opts !== 'object') {
throw new InvalidArgumentError('opts must be an object.')
}
if (opts.dispatcher) {
throw new InvalidArgumentError('opts.dispatcher is not supported by instance methods. Pass opts.dispatcher to the top-level undici functions or call the dispatcher instance method directly.')
}
if (this[kDestroyed] || this[kOnDestroyed]) {
throw new ClientDestroyedError()
}
if (this[kClosed]) {
throw new ClientClosedError()
}
return this[kDispatch](opts, handler)
} catch (err) {
if (typeof handler.onResponseError !== 'function') {
throw err
}
handler.onResponseError(null, err)
return false
}
}
}View on GitHub (pinned to 1b2de5e052)
Solutions
- Create a new Client/Pool after destroying the previous one.
- Guard dispatch with `if (client.destroyed) recreate();`.
- Sequence shutdown so in-flight dispatches complete before destroy() (use drain or await pending ops).
- Add an onResponseError handler to receive the error gracefully instead of throwing.
Example fix
// before await client.destroy() client.dispatch(opts, handler) // throws // after await client.destroy() client = new Client(url) client.dispatch(opts, handler)
Defensive patterns
Strategy: type-guard
Validate before calling
function dispatchOrRecreate(client, opts, handler) {
if (client.destroyed) {
client = new Client(client[kUrl]);
}
return client.dispatch(opts, handler);
} Type guard
!client.destroyed
Try / catch
try { client.dispatch(opts, handler); } catch (e) { if (e.code === 'UND_ERR_DESTROYED') { client = new Client(url); client.dispatch(opts, handler); } else throw e; } Prevention
- Never dispatch from a destroyed client; recreate it first.
- Coordinate shutdown so destroy() runs after in-flight dispatches.
- Implement onResponseError on handlers to absorb lifecycle errors gracefully.
When it happens
Trigger: Calling `client.dispatch(...)` after `await client.destroy()` (or while destroy callbacks are still queued). Fires at dispatcher-base.js:164-165.
Common situations: Reusing a pooled client after a connection-error-triggered destroy; shutdown race where one path destroys while another dispatches; destroy-on-idle timeout firing mid-request; forgetting to create a fresh Client after teardown.
Related errors
- UND_ERR_CLOSED
- UND_ERR_SOCKET
- UND_ERR_INVALID_ARG
- not implemented
- invalid interceptor, expected function received ${typeof int
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/ea135bac31dbe9d6.
Report an issue: GitHub.