news 2026/9/20 2:48:11

CANN Runtime 错误码 EH0003 深入解析:文件路径非法(Invalid Path)的触发原理与排查方法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN Runtime 错误码 EH0003 深入解析:文件路径非法(Invalid Path)的触发原理与排查方法

CANN Runtime 错误码 EH0003 深入解析:文件路径非法(Invalid Path)的触发原理与排查方法

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

导读

EH0003 是 CANN runtime(CANN 运行时组件)中一类面向用户的**文件路径非法(File Operation Error / Invalid Path)**错误码,当应用传入的配置文件路径不存在、无法解析或打开失败时,runtime 会以Path %s is invalid. Reason: %s.的固定模板向用户报告。本文以 EH0003-File_Operation_Error_Invalid_Path.md 为骨架,结合本仓库中该错误码的注册定义、底层格式化实现、两处真实触发源码与对应单元测试,完整还原 EH0003 的产生链路,并给出从报错信息到根因定位的实战排查步骤。

一、错误信息格式

EH0003 的报错格式固定如下,其中占位符%s的含义依次为文件路径报错原因

Path %s is invalid. Reason: %s.
占位符含义典型取值
第 1 个%s(path)传入或解析得到的文件路径/tmp/invalid.json./a.text
第 2 个%s(reason)具体的失败原因file open failed、无法解析真实路径时的系统错误信息

报错示例:

Path /tmp/invalid.json is invalid. Reason: file open failed.

这段报错表达了两层信息:第一,runtime 认为/tmp/invalid.json这个路径不合法;第二,非法的原因在于"文件打开失败"。排查时应优先关注 Reason 部分携带的具体失败原因,它直接指向根因方向。

二、EH0003 在错误码体系中的位置

EH0003 属于ACL Errors(EH 系列)外部错误码。在错误码索引文档 ACL-Errors.md 中,EH 系列覆盖了参数非法(EH0001/EH0002)、文件操作错误(EH0003/EH0004)、功能不支持(EH0006)等一系列通用用户侧错误;EH0003 的命名即表明其语义为File Operation Error - Invalid Path

从代码注册层面看,EH0003 在 runtime 中被统一定义为常量,供各模块复用:

  • src/acl/common/log_inner.h 中声明了constexpr const char_t* const INVALID_PATH_MSG = "EH0003";,与INVALID_PARAM_MSG(EH0001)、INVALID_NULL_POINTER_MSG(EH0002)等并列,属于 ACL 公共错误消息常量;
  • src/runtime_compact/c_base/src/error_manager.c 的错误码注册表ERROR_MAP中登记了该错误码的完整模板:
    {"EH0003", "Path %s is invalid. Reason: %s.", NULL, NULL, {"path", "reason"}},

    其中第 5 个字段{"path", "reason"}参数列表(argList),它规定了该错误模板各%s位对应的参数名,与报错格式中的占位符一一对应。这也是"报错格式中第 1 个%s为文件路径、第 2 个%s为报错原因"这一约定的代码级来源。

ERROR_MAP中的possibleCausesolution字段对 EH0003 均为空,说明该错误码不附带固定的原因与解决建议,需要根据每次上报时携带的 path 与 reason 动态判断。

三、哪些场景会触发 EH0003:从源码看触发链路

EH0003 并非只在"文件不存在"这一种场景下出现。在本仓库中,至少存在两处明确上报该错误码的源码路径,分别位于 runtime 配置读取与 JSON 配置解析两个环节。

3.1 场景一:runtime 配置路径无法解析或打开失败

src/acl/aclrt_impl/acl_rt_impl_base.cpp 中的GetStrFromConfigPath负责把外部传入的配置文件路径读取为字符串,它包含两道检查,任一失败都会上报 EH0003:

  1. 真实路径解析失败:调用mmRealPath(configPath, realPath, MMPA_MAX_PATH)对传入路径做规范化解析,若返回非EN_OK(例如路径指向不存在的目录、包含无法解析的符号链接、路径过长等),则上报:

    acl::AclErrorLogManager::ReportInputError( acl::INVALID_PATH_MSG, std::vector<const char*>({"path", "reason"}), std::vector<const char*>({configPath, formatErrMsg.c_str()})); ACL_LOG_ERROR("Invalid file: %s", configPath); return ACL_ERROR_INVALID_FILE;

    此时 Reason 携带的是mmGetErrorCode()格式化后的系统错误信息,报错示例中的/tmp/invalid.json即属于此类路径形态。

  2. 文件打开失败:路径解析成功后,用std::ifstream file(realPath, std::ios::binary)以二进制方式打开文件,若打开失败(文件不存在、权限不足、被占用等),则上报:

    acl::AclErrorLogManager::ReportInputError( acl::INVALID_PATH_MSG, std::vector<const char*>({"path", "reason"}), std::vector<const char*>({configPath, "file open failed"}));

    这正是错误码文档中报错示例Reason: file open failed.的源码出处。

无论哪一道检查失败,函数都会返回ACL_ERROR_INVALID_FILE给上层调用者,同时通过日志打印Invalid file: <path>Failed to open file: <path>便于定位。

3.2 场景二:JSON 配置文件非法路径检查

src/acl/common/json_parser.cpp 中JsonParser::IsValidFileName负责在解析 JSON 配置前校验文件名合法性,同样有两处 EH0003 上报:

  • mmRealPath(fileName, trustedPath, MMPA_MAX_PATH)返回非EN_OK时上报 EH0003,Reason 为AclGetErrorFormatMessage(mmGetErrorCode())得到的格式化错误信息,同时打印日志[Trans][RealPath]the file path %s is not like a real path, mmRealPath returns %d, errMessage is %s
  • mmStatGet(trustedPath, &pathStat)获取文件状态失败时再次上报 EH0003,Reason 为格式化错误信息,对应日志[Get][FileStatus]cannot get config file status, which path is %s, maybe does not exist, return %d, errcode %d

从这段实现可以推断:EH0003 的 Reason 部分并不总是固定的 "file open failed",它可能是一段来自底层系统调用的可读错误描述。因此排查 EH0003 时,必须完整读取 Reason 中携带的具体文本,而不能只依赖固定的示例。

3.3 参数上报机制小结

两处触发点都调用了acl::AclErrorLogManager::ReportInputError(INVALID_PATH_MSG, {"path", "reason"}, {path, reason}),其参数顺序与ERROR_MAP注册表(src/runtime_compact/c_base/src/error_manager.c)中的{"path", "reason"}严格对应,最终由 error manager 依据模板完成格式化并生成用户可见的报错文本。

四、单元测试中的 EH0003 验证

runtime 的错误码管理单元测试 tests/ut/runtime/runtime_c/testcase/c_base/error_manager_test.cc 对 EH0003 的格式化行为做了直接验证:

REPORT_INPUT_ERROR("EH0003", ARRAY("path", "reason", "value"), ARRAY("./a.text", "cannot find", "100")); char* errmsg = GetErrorMessage(); ASSERT_STREQ( errmsg, "EH0001: Value 25 for x is invalid. Reason: The value is too small.\r\n" " TraceBack (most recent call last):\r\n" " Argument ll must not be NULL.\r\n" " Path ./a.text is invalid. Reason: cannot find.\r\n");

该用例同时说明了两个重要行为:

  1. 模板格式化正确性:传入 path=./a.text、reason=cannot find时,最终输出Path ./a.text is invalid. Reason: cannot find.,与本文开头给出的报错格式完全一致;
  2. 参数冗余容忍:即使调用方多传了一个模板参数列表中不存在的value参数(ARRAY("path", "reason", "value")),EH0003 仍能正常格式化,多余参数不会导致模板错位或格式化失败,印证了 error manager 对参数数量的容错处理。

五、解决方法与排查步骤

5.1 官方解决方法

根据错误码文档 EH0003-File_Operation_Error_Invalid_Path.md,EH0003 的解决方法是:

根据报错检查文件是否存在。

5.2 结合源码的完整排查清单

仅"检查文件是否存在"还不够,结合 3.1 与 3.2 两处触发源码,建议按下述顺序逐项核查:

  1. 读取完整报错:先获取完整的 EH0003 文本,重点是Reason:之后的具体原因——它可能是file open failed,也可能是底层系统调用返回的可读错误描述,后者直接决定排查方向。

  2. 核对文件是否存在:使用ls -lstat等命令确认报错路径对应的文件真实存在,且不是指向失效位置的符号链接(mmRealPath解析失败同样会触发 EH0003)。

  3. 核对文件类型与权限

    • 路径指向的必须是普通文件,目录、设备文件等非普通文件在IsValidFileName中会命中"非普通文件"检查并报错(源码见 src/acl/common/json_parser.cpp,该分支使用 EH0004 模板);
    • 当前进程对文件须具备读取权限,且父目录具备可访问(可执行)权限,否则std::ifstream打开会失败并报file open failed
  4. 核对路径写法

    • 尽量使用绝对路径,避免依赖进程当前工作目录的相对路径;
    • 检查路径中是否包含未展开的环境变量、特殊字符或超出MMPA_MAX_PATH的长路径,这些都会导致mmRealPath解析失败。
  5. 结合日志定位:EH0003 上报时通常伴随ACL_LOG_ERROR日志输出,如Invalid file: <path>Failed to open file: <path>(src/acl/aclrt_impl/acl_rt_impl_base.cpp)或[Trans][RealPath]...[Get][FileStatus]...(src/acl/common/json_parser.cpp)。检索运行日志中与报错路径一致的关键字,可确认触发环节是"配置读取"还是"JSON 解析"。

  6. 确认返回码语义:在配置读取场景中,EH0003 对应的上层返回码是ACL_ERROR_INVALID_FILE(见 src/acl/aclrt_impl/acl_rt_impl_base.cpp),可在应用侧据此区分错误类别,与"参数非法(EH0001)""内存不足(EH0010)"等错误码区分处理。

六、小结

EH0003 是 CANN runtime 面向用户的通用文件路径错误码,其报错模板Path %s is invalid. Reason: %s.由错误码注册表 src/runtime_compact/c_base/src/error_manager.c 统一定义,实际触发点覆盖 runtime 配置路径读取(src/acl/aclrt_impl/acl_rt_impl_base.cpp)与 JSON 配置文件名校验(src/acl/common/json_parser.cpp)两条链路。排查时以报错中的 Reason 为第一线索,依次核对文件存在性、文件类型与权限、路径写法,并结合运行日志确认触发环节,即可快速收敛到根因。

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 2:46:31

付费墙与内容访问限制:规则内解锁文章全文的实用策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 2:46:23

MySQL UNION ALL 用法详解:结果集合并、去重与性能优化技巧

1. 先把UNION ALL的定位搞清楚&#xff1a;纵向拼接&#xff0c;不是横向拼接1.1 一句话说清它在做什么mysql里做结果合并&#xff0c;大家最常用到的就是UNION ALL。它的作用可以用一句话概括&#xff1a;把多个SELECT查询结果按行上下堆在一起&#xff0c;拼成一个更大的结果…

作者头像 李华
网站建设 2026/9/20 2:46:06

博图Openness七天打通:环境配置、对象树与自动化工程生成

从我做自动化项目那年开始&#xff0c;TIA Portal 就成了每天都在用的工具。后来接触的项目越来越大&#xff0c;几十台变频器、上千个 IO 点、标准控制逻辑重复出现&#xff0c;每天花在“拖拽组态”上的时间越来越多&#xff0c;我终于开始注意到 TIA Portal Openness 这个接…

作者头像 李华
网站建设 2026/9/20 2:44:14

VxLAN为何撑不起AI算力集群?SRv6确定性网络如何破局

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 2:43:30

AI编程工具选型指南:Vibe Coding实战对比与避坑建议

最近一段时间&#xff0c;我朋友圈里聊得最多的一个词&#xff0c;就是 Vibe Coding。你说它是新概念吧&#xff0c;其实核心思路早就有了——用自然语言描述需求&#xff0c;让 AI 把代码写出来&#xff0c;人主要负责 review、修修补补和调整方向。但这东西真正落地之后&…

作者头像 李华
网站建设 2026/9/20 2:41:58

Qt5.14.2 aarch64静态交叉编译实战:从环境搭建到部署避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华