{"id":"a68585bb22d234fa","repo":"sindresorhus/got","slug":"econnreset","errorCode":"ECONNRESET","errorMessage":"The server aborted pending request","messagePattern":"The server aborted pending request","errorType":"exception","errorClass":"ReadError","httpStatus":null,"severity":"error","filePath":"source/core/index.ts","lineNumber":1111,"sourceCode":"\n\t\t\tthis._aborted = true;\n\n\t\t\tthis._beforeError(new ReadError(error, this));\n\t\t});\n\n\t\tresponse.once('aborted', () => {\n\t\t\t// Without Content-Length, connection close is the intended EOF signal (RFC 9110 §8.6),\n\t\t\t// not a premature abort. For wrapped decompression streams, rely on the native\n\t\t\t// response completion state because the wrapper strips `content-length`.\n\t\t\tif (this._responseSize === undefined && nativeResponse.complete) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._aborted = true;\n\n\t\t\t// Check if there's a content-length mismatch to provide a more specific error\n\t\t\tif (!this._checkContentLengthMismatch()) {\n\t\t\t\tthis._beforeError(new ReadError({\n\t\t\t\t\tname: 'Error',\n\t\t\t\t\tmessage: 'The server aborted pending request',\n\t\t\t\t\tcode: 'ECONNRESET',\n\t\t\t\t}, this));\n\t\t\t}\n\t\t});\n\n\t\tlet canFinalizeResponse = false;\n\t\tconst handleResponseEnd = () => {\n\t\t\tif (\n\t\t\t\t!canFinalizeResponse\n\t\t\t\t|| !response.readableEnded\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcanFinalizeResponse = false;\n","sourceCodeStart":1093,"sourceCodeEnd":1129,"githubUrl":"https://github.com/sindresorhus/got/blob/e3924aa1e53a6ca3eb93a43618ce532442a89b40/source/core/index.ts#L1093-L1129","documentation":"Produced at source/core/index.ts:1111 in the `response.once('aborted', ...)` handler. When the underlying IncomingMessage emits `aborted` (the server closed the connection before sending a complete response) and there is no Content-Length mismatch to report instead, got wraps the event in a ReadError with code ECONNRESET. The guard at line 1103 first allows close-delimited responses (no Content-Length) whose nativeResponse.complete is true, because in that case the close was the intended EOF, not an abort.","triggerScenarios":"Server closes the TCP connection before finishing the response body; upstream gateway timeout that drops the socket mid-stream; server crashed mid-response; reverse proxy recycled the worker; client-side socket was forcibly reset by a NAT or firewall after a long idle gap during a slow response.","commonSituations":"Long-running downloads behind an aggressive proxy timeout, upstream service instability, deployments that restart servers mid-request, mobile/flaky networks that reset connections, or load balancers that drop connections after a fixed byte quota.","solutions":["Enable retry on ECONNRESET (got does this by default) and increase retry.limit if the upstream is known to be flaky.","Lower `timeout.request` so the client gives up before the server's idle-drop, or raise the upstream/proxy timeout to exceed your longest response.","Switch to HTTP/2 (`http2: true`) which multiplexes and recovers more gracefully from connection issues."],"exampleFix":"// before\nawait got('https://flaky-api/large', { timeout: { request: 60000 } });\n\n// after — retry reset connections, keep timeouts realistic\nawait got('https://flaky-api/large', {\n  timeout: { request: 30000 },\n  retry: { limit: 4, errorCodes: ['ECONNRESET', 'ETIMEDOUT', 'EPIPE'] }\n});","handlingStrategy":"retry","validationCode":"// Configure retry to cover connection resets during response.\nconst options = {\n  retry: {\n    limit: 4,\n    errorCodes: ['ECONNRESET', 'ETIMEDOUT', 'ECONNREFUSED', 'EPIPE']\n  },\n  timeout: { request: 30000 }\n};","typeGuard":null,"tryCatchPattern":"import {RequestError} from 'got';\n\ntry {\n  await got(url, options);\n} catch (error) {\n  if (error instanceof RequestError && error.code === 'ECONNRESET' && /server aborted pending request/.test(error.message)) {\n    // got already retried up to retry.limit; surface as a transient upstream issue\n    throw new Error('Upstream closed the connection mid-response after retries', { cause: error });\n  }\n  throw error;\n}","preventionTips":["Keep ECONNRESET in retry.errorCodes (it is default) and size retry.limit to upstream flakiness.","Set timeout.request shorter than the upstream/proxy idle drop so the client retries before the server gives up.","For large downloads, consider HTTP/2 (http2: true) which handles connection reuse better."],"tags":["network","econnreset","server-abort","retry"],"analyzedSha":"e3924aa1e53a6ca3eb93a43618ce532442a89b40","analyzedAt":"2026-08-03T19:22:24.770Z","schemaVersion":2}