{"id":"265a834aab0d9a54","repo":"expressjs/express","slug":"econnaborted","errorCode":"ECONNABORTED","errorMessage":"Request aborted","messagePattern":"Request aborted","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"lib/response.js","lineNumber":933,"sourceCode":"    if (err) return req.next(err);\n    self.send(str);\n  };\n\n  // render\n  app.render(view, opts, done);\n};\n\n// pipe the send file stream\nfunction sendfile(res, file, options, callback) {\n  var done = false;\n  var streaming;\n\n  // request aborted\n  function onaborted() {\n    if (done) return;\n    done = true;\n\n    var err = new Error('Request aborted');\n    err.code = 'ECONNABORTED';\n    callback(err);\n  }\n\n  // directory\n  function ondirectory() {\n    if (done) return;\n    done = true;\n\n    var err = new Error('EISDIR, read');\n    err.code = 'EISDIR';\n    callback(err);\n  }\n\n  // errors\n  function onerror(err) {\n    if (done) return;\n    done = true;","sourceCodeStart":915,"sourceCodeEnd":951,"githubUrl":"https://github.com/expressjs/express/blob/a3714473feb3d2908add734d340e7755fd85e0a3/lib/response.js#L915-L951","documentation":"Express's internal `sendfile` helper (lib/response.js:929-936) wraps the `send` file-streaming module for `res.sendFile()`/`res.download()`. When the underlying stream emits an abort — or finishes with an ECONNRESET (line 969 routes that to `onaborted`) — Express synthesizes `new Error('Request aborted')` with `code: 'ECONNABORTED'` and passes it to your sendFile callback (or to `next()` if none). It means the client disconnected before the file transfer completed; the server side did nothing wrong.","triggerScenarios":"Calling `res.sendFile(path, cb)` or `res.download(path, cb)` while the client closes the socket mid-transfer: the user hits stop/navigates away, an HTTP client times out or calls `request.abort()`, a proxy (nginx, ELB) kills the upstream connection, or a video/PDF viewer issues range requests and drops earlier ones. It is delivered via the callback, or hits your error middleware if you passed none.","commonSituations":"Log noise from users cancelling large downloads or streaming video with range requests; load balancers with idle timeouts shorter than the file transfer time; frontend fetch calls with AbortController timeouts; health checkers/scanners that disconnect immediately. Developers often mistake it for a server bug and crash the process by re-throwing it, or double-respond by treating it as a case needing an error page.","solutions":["Handle it in the sendFile/download callback: if (err && err.code === 'ECONNABORTED') just log at debug level and return — the client is gone, do not attempt another response.","In global error middleware, check `err.code === 'ECONNABORTED'` (and `res.headersSent`) and swallow/log instead of rendering a 500.","If aborts are frequent and unwanted, raise proxy/load-balancer timeouts (e.g. nginx `proxy_read_timeout`, ALB idle timeout) above your largest transfer time.","For very large files, serve via a static file server/CDN or `express.static` with range support so retries are cheap."],"exampleFix":"// before\nres.download('/data/report.zip', function (err) {\n  if (err) next(err); // turns every client cancel into a 500 in logs\n});\n\n// after\nres.download('/data/report.zip', function (err) {\n  if (err) {\n    if (err.code === 'ECONNABORTED') {\n      debug('client aborted download');\n      return; // client disconnected — nothing to send\n    }\n    return next(err);\n  }\n});","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isConnAborted(err) {\n  return err != null && typeof err === 'object' && err.code === 'ECONNABORTED';\n}","tryCatchPattern":"res.sendFile(filePath, function (err) {\n  if (err) {\n    if (err.code === 'ECONNABORTED') {\n      // Client disconnected mid-transfer; nothing to send. Log and stop.\n      console.warn('client aborted download of %s', filePath);\n      return;\n    }\n    next(err);\n  }\n});","preventionTips":["Always pass a callback to res.sendFile/res.download so transfer errors are delivered to you instead of crashing or being silently dropped","Treat ECONNABORTED as a client-side event, not a server fault — log it at low severity and do not attempt to write another response","Check res.headersSent before trying to send an error response in the callback, since headers are usually already sent when the abort happens","Set sensible timeouts (server.requestTimeout, reverse-proxy timeouts) so slow clients abort predictably rather than hanging sockets","Expect aborts under load and on mobile networks; make download endpoints idempotent so a retried request is safe"],"tags":["network","express","sendfile","client-abort","http"],"analyzedSha":"a3714473feb3d2908add734d340e7755fd85e0a3","analyzedAt":"2026-07-31T18:55:36.968Z","schemaVersion":2}