{"id":"704eb693575d4b7b","repo":"axios/axios","slug":"etimedout-econnaborted","errorCode":"ETIMEDOUT|ECONNABORTED","errorMessage":"timeout of ${_config.timeout}ms exceeded","messagePattern":"timeout of (.+?)ms exceeded","errorType":"exception","errorClass":"AxiosError","httpStatus":null,"severity":"error","filePath":"lib/adapters/xhr.js","lineNumber":166,"sourceCode":"        const err = new AxiosError(msg, AxiosError.ERR_NETWORK, config, request);\n        // attach the underlying event for consumers who want details\n        err.event = event || null;\n        reject(err);\n        done();\n        request = null;\n      };\n\n      // Handle timeout\n      request.ontimeout = function handleTimeout() {\n        let timeoutErrorMessage = _config.timeout\n          ? 'timeout of ' + _config.timeout + 'ms exceeded'\n          : 'timeout exceeded';\n        const transitional = _config.transitional || transitionalDefaults;\n        if (_config.timeoutErrorMessage) {\n          timeoutErrorMessage = _config.timeoutErrorMessage;\n        }\n        reject(\n          new AxiosError(\n            timeoutErrorMessage,\n            transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,\n            config,\n            request\n          )\n        );\n        done();\n\n        // Clean up request\n        request = null;\n      };\n\n      // Remove Content-Type if data is undefined\n      requestData === undefined && requestHeaders.setContentType(null);\n\n      // Add headers to the request\n      if ('setRequestHeader' in request) {\n        utils.forEach(toByteStringHeaderObject(requestHeaders), function setRequestHeader(val, key) {","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/axios/axios/blob/c3f553c740ebf3dff5e22dae24e9caaafafddd2d/lib/adapters/xhr.js#L148-L184","documentation":"Rejected from the XHR adapter's `ontimeout` handler when the request exceeded `config.timeout` milliseconds (set directly on request.timeout at line 41, so the browser enforces it across the whole request lifetime). With the default transitional.clarifyTimeoutError=false the code is ECONNABORTED for backward compatibility; setting clarifyTimeoutError: true yields the more accurate ETIMEDOUT. The message can be overridden with config.timeoutErrorMessage.","triggerScenarios":"axios.get(url, {timeout: 5000}) where the server takes longer than 5s to fully respond; large uploads/downloads on slow links exceeding the timeout (XHR timeout covers the entire exchange, not just time-to-first-byte); an instance created with a small default timeout applied to a slow endpoint.","commonSituations":"A global axios.create({timeout: 3000}) instance later used for slow report/export endpoints; cold-start latency on serverless backends; timeouts appearing only in production due to network distance; confusing the ECONNABORTED code with an abort — check whether the message says 'timeout of Nms exceeded' to tell them apart.","solutions":["Raise config.timeout for the slow endpoint (or set it per-request rather than globally), after confirming the server genuinely needs longer.","Investigate why the server is slow — the timeout is usually the messenger, not the bug.","Set transitional: { clarifyTimeoutError: true } so timeouts get code ETIMEDOUT and are distinguishable from aborts in error handling.","Add retry-with-backoff for idempotent requests that time out intermittently.","For user-driven cancellation of long requests, prefer AbortSignal.timeout(ms) via the signal option, which composes with other abort reasons."],"exampleFix":"// before\nconst api = axios.create({ timeout: 3000 });\nawait api.get('/reports/annual'); // times out, code ECONNABORTED\n// after\nawait api.get('/reports/annual', {\n  timeout: 30000,\n  transitional: { clarifyTimeoutError: true }, // rejects with ETIMEDOUT\n});","handlingStrategy":"retry","validationCode":"const config = { timeout: 10000 };\nif (!Number.isFinite(config.timeout) || config.timeout <= 0) {\n  throw new Error('timeout must be a positive number of milliseconds');\n}","typeGuard":"import axios from 'axios';\nfunction isTimeoutError(err) {\n  return axios.isAxiosError(err) &&\n    (err.code === 'ETIMEDOUT' || err.code === 'ECONNABORTED') &&\n    /timeout/i.test(err.message);\n}","tryCatchPattern":"try {\n  await axios.get(url, { timeout: 10000 });\n} catch (err) {\n  if (axios.isAxiosError(err) && (err.code === 'ETIMEDOUT' || err.code === 'ECONNABORTED')) {\n    // slow server/network: retry idempotent requests with a longer timeout or backoff\n  } else {\n    throw err;\n  }\n}","preventionTips":["Set an explicit timeout sized from real p99 latency of the endpoint — the default of 0 means axios waits forever.","Check both ETIMEDOUT and ECONNABORTED when detecting timeouts; older axios versions used ECONNABORTED unless transitional.clarifyTimeoutError is enabled.","Set transitional: { clarifyTimeoutError: true } to get the unambiguous ETIMEDOUT code.","Retry timeouts only for idempotent requests, with backoff — the server may still have processed the original.","Set per-request timeouts for known-slow endpoints instead of one instance-wide value."],"tags":["timeout","xhr","config"],"analyzedSha":"c3f553c740ebf3dff5e22dae24e9caaafafddd2d","analyzedAt":"2026-07-31T18:49:43.633Z","schemaVersion":2}