{"record":{"id":"3d2472d70de1f6a1","repo":"nodejs/node","slug":"und-err-closed","errorCode":"UND_ERR_CLOSED","errorMessage":"The client is closed","messagePattern":"The client is closed","errorType":"exception","errorClass":"ClientClosedError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/dispatcher/dispatcher-base.js","lineNumber":169,"sourceCode":"    if (!handler || typeof handler !== 'object') {\n      throw new InvalidArgumentError('handler must be an object')\n    }\n\n    try {\n      if (!opts || typeof opts !== 'object') {\n        throw new InvalidArgumentError('opts must be an object.')\n      }\n\n      if (opts.dispatcher) {\n        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.')\n      }\n\n      if (this[kDestroyed] || this[kOnDestroyed]) {\n        throw new ClientDestroyedError()\n      }\n\n      if (this[kClosed]) {\n        throw new ClientClosedError()\n      }\n\n      return this[kDispatch](opts, handler)\n    } catch (err) {\n      if (typeof handler.onResponseError !== 'function') {\n        throw err\n      }\n\n      handler.onResponseError(null, err)\n\n      return false\n    }\n  }\n}\n\nmodule.exports = DispatcherBase\n","sourceCodeStart":151,"sourceCodeEnd":186,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/dispatcher/dispatcher-base.js#L151-L186","documentation":"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.","triggerScenarios":"Calling `client.dispatch(...)` after `await client.close()`. Fires at dispatcher-base.js:168-169.","commonSituations":"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.","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."],"exampleFix":"// before\nawait client.close()\nclient.dispatch(opts, handler) // throws\n// after\nawait client.close()\nconst client2 = new Client(url)\nclient2.dispatch(opts, handler)","handlingStrategy":"type-guard","validationCode":"function ensureOpen(client) {\n  if (client.closed || client.destroyed) {\n    return new Client(client.url);\n  }\n  return client;\n}","typeGuard":"!client.closed && !client.destroyed","tryCatchPattern":"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; }","preventionTips":["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."],"tags":["undici","dispatcher","lifecycle","closed","state-error"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}