nodejs/node · error · ClientClosedError
UND_ERR_CLOSED
UND_ERR_CLOSED
Error message
The client is closed
What it means
ClientClosedError (UND_ERR_CLOSED) thrown by dispatch() when the client has been closed via close() but not yet destroyed. close() stops accepting new dispatches while letting in-flight ones finish; any new dispatch during that window throws. As with destroyed, an onResponseError handler receives the error instead.
Source
Thrown at deps/undici/src/lib/dispatcher/dispatcher-base.js:169
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
}
}
}
module.exports = DispatcherBase
View on GitHub (pinned to 1b2de5e052)
Solutions
- Do not dispatch after close(); create a new client for further work.
- Guard with `if (client.closed) { ... }` before dispatching.
- Use destroy() if you want immediate teardown, or wait for close to settle before re-creating.
- Implement onResponseError on the handler to absorb the error.
Example fix
// before await client.close() client.dispatch(opts, handler) // throws // after await client.close() const client2 = new Client(url) client2.dispatch(opts, handler)
Defensive patterns
Strategy: type-guard
Validate before calling
function ensureOpen(client) {
if (client.closed || client.destroyed) {
return new Client(client.url);
}
return client;
} Type guard
!client.closed && !client.destroyed
Try / catch
try { client.dispatch(opts, handler); } catch (e) { if (e.code === 'UND_ERR_CLOSED') { const c = new Client(url); c.dispatch(opts, handler); } else throw e; } Prevention
- Do not dispatch after close(); spin up a new client.
- Guard dispatch with checks on client.closed / client.destroyed.
- Choose close() (graceful) vs destroy() (immediate) deliberately.
When it happens
Trigger: Calling `client.dispatch(...)` after `await client.close()`. Fires at dispatcher-base.js:168-169.
Common situations: Graceful shutdown that calls close() but a queued task then tries to dispatch; retry logic that does not check `client.closed`; mixing close() and destroy() semantics and dispatching in between.
Related errors
- UND_ERR_DESTROYED
- UND_ERR_INVALID_ARG
- UND_ERR_SOCKET
- not implemented
- invalid interceptor, expected function received ${typeof int
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/3d2472d70de1f6a1.
Report an issue: GitHub.