首页
/ Axios 错误处理深度解析:AxiosError 结构、错误码、超时区分与敏感信息脱敏

Axios 错误处理深度解析:AxiosError 结构、错误码、超时区分与敏感信息脱敏

2026-09-04 23:11:57作者:廉彬冶Miranda

axios 默认在请求失败时让 Promise 被 reject,而失败的具体形态由 AxiosError 对象承载。本文基于官方文档 docs/fr/pages/advanced/error-handling.md 并结合 axios 源码,完整解析 axios 抛出的错误结构(messagecodestatusconfigrequestresponse 等字段)、axios 内部识别的全部错误码及其在源码中的产生位置,以及 validateStatus 自定义判定、timeout 超时错误区分(ECONNABORTEDETIMEDOUT)、畸形 HTTP(S) URL 的严格校验,还有通过 toJSON() 序列化错误和使用 redact 配置避免密钥泄漏的实战方案。读完本文,你可以在浏览器与 Node.js 环境下编写结构清晰、可区分超时/网络/取消等错误类型、且不会在日志中泄露凭据的错误处理代码。

AxiosError:axios 错误的统一载体

axios 抛出的绝大多数错误都是 AxiosError 实例(由原生 Error 派生),文档给出的通用结构如下:

属性 定义
message 错误消息与失败状态码的简短摘要。
name 标识错误来源。来自 axios 的错误,该值始终为 AxiosError
stack 提供错误的调用堆栈。
config 请求发起时 axios 的配置对象,包含用户为请求/实例设置的各项配置。
code 代表被 axios 识别的错误类型,具体取值见下一节的错误码表。
status HTTP 响应状态码。

此外,AxiosError 实例还带有一个布尔标记 isAxiosError = true,这正是 axios.isAxiosError(error) 的判定依据。从源码看,isAxiosError.js 中该函数只做一次属性检查:

export default function isAxiosError(payload) {
  return utils.isObject(payload) && payload.isAxiosError === true;
}

而在 AxiosError.js 的构造函数中,各字段被显式挂到实例上(第 160–168 行):

this.name = 'AxiosError';
this.isAxiosError = true;
code && (this.code = code);
config && (this.config = config);
request && (this.request = request);
if (response) {
  this.response = response;
  this.status = response.status;
}

可以据此推断出文档中三个错误分支与源码字段的对应关系:只有拿到服务端响应(response)时才设置 status;只有请求已发出但无响应时 request 才有值;而配置阶段的错误通常既没有 request 也没有 response,只留下 configmessage

axios 内部识别的错误码(code)

文档列出了 axios 可识别的全部错误码。这些错误码以静态属性形式定义在 AxiosError.js 中,可统一通过 AxiosError.ERR_NETWORK 等引用:

错误码 含义
ERR_BAD_OPTION_VALUE axios 配置中提供了无效或不受支持的值。
ERR_BAD_OPTION axios 配置中提供了无效的选项。
ECONNABORTED 通常表示请求超时(除非设置了 transitional.clarifyTimeoutError),或被浏览器/插件中止。
ETIMEDOUT 请求超过了 axios 默认超时时间。需将 transitional.clarifyTimeoutError 设为 true,否则抛出的仍是通用的 ECONNABORTED
ERR_NETWORK 网络类问题。在浏览器中,CORS 违规或混合内容(mixed content)也可能导致此错误;出于安全考虑,浏览器不允许 JS 得知真实原因,请查看控制台。
ERR_FR_TOO_MANY_REDIRECTS 请求被重定向的次数超过了 axios 配置中指定的最大值。
ERR_DEPRECATED 使用了 axios 中已被弃用的功能或方法。
ERR_BAD_RESPONSE 响应无法被正确解析或格式不符合预期,通常对应 5xx 状态码。
ERR_BAD_REQUEST 请求格式不符合预期或缺少必需参数,通常对应 4xx 状态码。
ERR_CANCELED 功能或方法被用户通过 AbortSignal(或 CancelToken)显式取消。
ERR_NOT_SUPPORT 当前 axios 运行环境不支持该功能或方法。
ERR_INVALID_URL axios 请求提供了无效的 URL。
ERR_FORM_DATA_DEPTH_EXCEEDED 序列化 params 或表单数据时,某对象深度超过了配置的 maxDepth,默认限制 100 层。可参考 请求配置文档 中的 paramsSerializerformSerializer 说明。

源码中可以找到几个代表性错误码的产生点:

  • ERR_BAD_REQUEST / ERR_BAD_RESPONSEsettle.js 在响应判定失败时抛出,状态码 4xx/5xx 与错误码的对应关系即在此处确定:
reject(new AxiosError(
  'Request failed with status code ' + response.status,
  response.status >= 400 && response.status < 500 ? AxiosError.ERR_BAD_REQUEST : AxiosError.ERR_BAD_RESPONSE,
  response.config,
  response.request,
  response
));
  • ERR_INVALID_URLbuildFullPath.js 中的 assertValidHttpProtocolURL 抛出(详见下文"畸形 URL"一节),此外 fromDataURI.js 在解析非法 data URI 时也会使用该错误码。
  • ERR_FORM_DATA_DEPTH_EXCEEDED 分别由 toFormData.jsformDataToJSON.js 在递归序列化超过 maxDepth 时抛出。

捕获与处理错误:response / request / config 三分支

axios 的默认行为是:请求失败时 reject Promise。捕获错误后,推荐的判断顺序是"先查 error.response,再查 error.request,最后处理配置阶段的错误"。这是文档给出的标准示例:

axios.get("/user/12345").catch(function (error) {
  if (error.response) {
    // 请求已发出,且服务端返回了非 2xx 的状态码
    console.log(error.response.data);
    console.log(error.response.status);
    console.log(error.response.headers);
  } else if (error.request) {
    // 请求已发出,但未收到任何响应
    // 浏览器中 `error.request` 是 XMLHttpRequest 实例,
    // Node.js 中是 http.ClientRequest 实例
    console.log(error.request);
  } else {
    // 请求配置阶段就发生了错误
    console.log("Error", error.message);
  }
  console.log(error.config);
});

这个三分支结构之所以可靠,是因为它直接对应 AxiosError 构造函数的赋值逻辑:response 分支意味着响应已存在(服务端返回了非 2xx);request 分支意味着请求已挂到实例上但响应缺失(网络中断、超时、CORS 等);否则就是配置校验、URL 解析等问题,此时只有 configmessage 可用。在 Node.js 环境中,http.js 适配器抛错时会把原生 http.ClientRequest 作为 request 传入;浏览器中则由 xhr.js 传入 XMLHttpRequest 实例。

使用 validateStatus 自定义"何为失败"

axios 的默认判定是 status >= 200 && status < 300 时 resolve,否则 reject。通过配置项 validateStatus 可以覆盖这一条件,自行决定哪些 HTTP 状态码应当触发错误:

axios.get("/user/12345", {
  validateStatus: function (status) {
    return status < 500; // 只有状态码小于 500 才视为成功
  },
});

默认实现在 defaults/index.js 中定义,判定逻辑则在 settle.js 执行:若 validateStatus(response.status) 返回真值则 resolve,否则构造 AxiosError 并 reject。此外 mergeConfig.js 中还有一个 transitional.validateStatusUndefinedResolves 细节:当请求级配置显式传入 validateStatus: undefined 且该过渡开关为 false 时,会回退到实例级 validateStatus,这允许你用请求级配置覆盖实例默认值。

处理超时:ECONNABORTED 与 ETIMEDOUT 的区分

当请求超过配置的 timeout 时,axios 默认以 ECONNABORTED 拒绝 Promise。若希望获得更精确的 ETIMEDOUT 错误码,需要设置 transitional.clarifyTimeoutError: true

async function fetchWithTimeout() {
  try {
    const response = await axios.get("https://example.com/data", {
      timeout: 5000, // 5 秒
      transitional: {
        // 若希望用 ETIMEDOUT 替代 ECONNABORTED,设为 true
        clarifyTimeoutError: true,
      },
    });

    console.log("Response:", response.data);
  } catch (error) {
    if (axios.isAxiosError(error)) {
      if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") {
        console.error("Request timed out. Please try again.");
        return;
      }

      console.error("Axios error:", error.message);
      return;
    }

    console.error("Unexpected error:", error);
  }
}

源码层面,transitional.js 显示 clarifyTimeoutError 的默认值是 false,因此不显式开启时超时一律是 ECONNABORTED。浏览器适配器的 request.ontimeout 处理(xhr.js)体现了这一切换逻辑:

reject(
  new AxiosError(
    timeoutErrorMessage,
    transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
    config,
    request
  )
);

Node.js 适配器 http.js 中的超时处理采用完全相同的三元表达式;另外 composeSignals.js 在组合 AbortSignal 超时时直接抛出 ETIMEDOUT,可据此推断不同触发路径下错误码可能略有差异,编写兜底逻辑时建议同时兼容 ECONNABORTEDETIMEDOUT

生产环境务必设置 timeout,否则被阻塞的请求可能永远处于挂起状态。相关配置项参见 请求配置文档 中的 timeouttransitional.clarifyTimeoutError 说明。

畸形 HTTP(S) URL:ERR_INVALID_URL 的严格校验

axios 会拒绝 urlbaseURL 中协议后缺少 //http:/https: URL。例如 https:example.comhttps:/example.com 不会被浏览器或 Node.js 的 URL 解析器"静默修正",而是直接抛出 codeERR_INVALID_URLAxiosError。请使用 https://example.com 这类格式正确的 URL。

错误消息会明确指出有问题的 URL,例如:

Invalid URL "https:example.com": missing "//" after protocol

这一行为在 buildFullPath.js 中实现,核心是一个正则与断言函数:

const malformedHttpProtocol = /^https?:(?!\/\/)/i;

function assertValidHttpProtocolURL(url, config) {
  if (typeof url === 'string') {
    const normalizedURL = normalizeURLForProtocolCheck(url);
    if (malformedHttpProtocol.test(normalizedURL)) {
      throw new AxiosError(
        `Invalid URL ${JSON.stringify(redactSensitiveURLParts(normalizedURL))}: missing "//" after protocol`,
        AxiosError.ERR_INVALID_URL,
        config
      );
    }
  }
}

其中 normalizeURLForProtocolCheck.js 会先对齐 WHATWG URL 的预处理规则:剔除前导空白字符并移除 \t\n\r 控制字符后再做协议检查,防止通过控制字符绕过校验。

安全动机:这种严格校验能阻止畸形 URL 绕过 baseURL 拼接逻辑或 URL 白名单机制。更重要的是,错误消息中对 URL 的展示做了系统性脱敏(redactSensitiveURLParts):

  • 保留协议、主机、路径与查询参数名,使请求仍可被识别;
  • 掩码凭据(userinfo)、查询参数值与 fragment 内容,替换为 [REDACTED ****] 标记。

之所以必须"系统性"掩码,是因为 AxiosError.message 总是被 toJSON() 原样序列化进日志,而配置中的 redact 选项只能清理 config 下的键值,无法清理已经生成好的错误消息文本。单元测试 buildFullPath.test.js 验证了这一行为,例如:

'Invalid URL "https:[REDACTED ****]@api.example.com/v1?apikey=[REDACTED ****]&id=[REDACTED ****]#token=[REDACTED ****]&[REDACTED ****]": missing "//" after protocol'

序列化错误:toJSON() 与 redact 脱敏配置

使用 toJSON() 可以获得包含更多信息的错误对象快照:

axios.get("/user/12345").catch(function (error) {
  console.log(error.toJSON());
});

AxiosError.jstoJSON() 实现可以看到,返回对象包含标准字段(messagenamestack)、浏览器扩展字段(descriptionfileName 等)以及 axios 特有字段(configcodestatus)。

为了避免把密钥从 error.config 中打进日志,可以在请求配置里传入 redact 数组。调用 AxiosError#toJSON() 时,任何深度的、大小写不敏感的同名配置键都会被替换为脱敏标记:

axios.get("/user/12345", {
  headers: { Authorization: "Bearer token" },
  redact: ["authorization"]
}).catch(function (error) {
  console.log(error.toJSON().config.headers.Authorization); // [REDACTED ****]
});

实现上,toJSON() 检测到 config.redact 是非空数组时,会调用 redactConfigAxiosError.js)生成脱敏后的配置快照:它把 redact 中的键统一转为小写后逐一匹配,递归遍历普通对象与数组,对 AxiosHeaders 实例先调用其 toJSON() 再处理,并通过 seen 列表短路循环引用。命中键的值被替换为模块级常量 REDACTED = '[REDACTED ****]'AxiosError.test.jstoJSON redaction via config.redact 测试组覆盖了完整语义:redact 未定义或为空数组时保持旧序列化行为;顶层键、嵌套对象(auth.passwordproxy.auth.password)、AxiosHeaders 实例、对象数组内的键均可被正确掩码;并且对继承的 redact 访问器与原型污染场景做了防护。

小结:可落地的错误处理清单

结合文档与源码,可归纳出如下可复制的错误处理实践:

  1. axios.isAxiosError(error) 确认错误来源,再按 error.responseerror.request → 其他 的顺序三分支处理;
  2. 依赖 error.code 而非 error.message 文本做类型分发:ERR_CANCELED(取消)、ETIMEDOUT/ECONNABORTED(超时)、ERR_NETWORK(网络/CORS)、ERR_BAD_REQUEST/ERR_BAD_RESPONSE(4xx/5xx);
  3. validateStatus 精确控制哪些状态码算失败,例如把 404 视为"正常空结果"时返回 status < 500
  4. 生产环境设置 timeout,并按需开启 transitional.clarifyTimeoutError 以获得可区分的 ETIMEDOUT
  5. 日志输出统一走 error.toJSON(),并对 Authorizationtokenpassword 等键配置 redact;注意错误消息文本本身的脱敏只由 axios 在生成时完成(如畸形 URL 场景),redact 无法回溯清理。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384