CANN opbase 错误码 EZ1004/EZ1005 全解:文件解析失败(File Operation Error Parse)的成因与排查实践
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
导读
EZ1004 与 EZ1005 是 CANN 算子库基础框架 opbase 中Nnopbase Errors错误类下的File_Operation_Error_Parse(文件解析失败)错误码,二者共用同一错误格式Failed to parse file %s. Reason: %s.,分别面向"解析器抛出的语法/运行时异常"与"文件内容不符合标准结构"两类场景。本文以 EZ1004 官方错误说明 为骨架,结合仓库中错误码的注册与触发源码,讲清该错误码的产生链路、典型报错含义与完整排查思路,帮助开发者在算子二进制、kernel 库 JSON 等配置文件解析失败时快速定位并恢复。
一、错误码定位:它在错误体系中的位置
在 opbase 仓库中,NNopbase(AclNN 算子执行框架)层的错误码集中定义于 Nnopbase-Errors 索引页,涵盖 EZ1001(参数错误)到 EZ1014(执行错误)共 14 个错误码。其中:
- EZ1003:文件打开失败(
File_Operation_Error_Open) - EZ1004:文件解析失败(
File_Operation_Error_Parse) - EZ1005:文件解析失败,内容非法(
File_Operation_Error_Parse,与 EZ1004 同 errTitle,但语义指向"内容非标准结构")
在错误码注册表 src/nnopbase/composite_op/log/op_error_manager.cpp 中,EZ1004 与 EZ1005 的元信息如下:
| 字段 | EZ1004 | EZ1005 |
|---|---|---|
| errClass | Nnopbase Errors | Nnopbase Errors |
| errTitle | File_Operation_Error_Parse | File_Operation_Error_Parse |
| ErrCode | EZ1004 | EZ1005 |
| ErrMessage | Failed to parse file %s. Reason: %s. | Failed to parse file %s. Reason: %s. |
| Arglist | file, reason | file, reason |
| suggestion.Possible Cause | N/A | 1. 自定义算子 JSON 文件损坏 2. 内置算子 JSON 文件损坏 |
| suggestion.Solution | N/A | 1. 重装自定义算子包 2. 重装内置算子包 |
同一份错误码定义(errTitle、ErrMessage)在算子侧(Operator Errors类,EZ0031)也存在,对应文档见 EZ0031-File_Operation_Error_Parse。EZ0031 面向算子开发阶段的自定义配置文件解析,而 EZ1004/EZ1005 面向运行时框架对算子 JSON 元数据与二进制的解析,两者适用阶段不同,排查时需区分。
二、错误格式解析:%s 占位符的语义
官方文档明确规定,EZ1004 与 EZ1005 的错误信息格式为:
Failed to parse file %s. Reason: %s.两个%s占位符按顺序分别表示:
- 文件名(file):解析失败的目标文件完整路径,例如算子 kernel 的 JSON 描述文件、ops-info 配置或二进制文件路径;
- 错误原因(reason):导致解析失败的具体原因,通常来自 JSON 解析器抛出的异常信息,或框架内部校验失败的自定义原因文本。
该格式与源码中的宏定义完全一致。在 src/nnopbase/common/inc/nnopbase_error_msg.h 中,EZ1004 与 EZ1005 分别由两个宏生成:
#define OP_LOGE_FOR_FILE_OPERATION_ERROR_PARSE(file, reason) \ do { \ std::string msg = std::string("Failed to parse file ") + file + \ ". Reason: " + reason + "."; \ const std::vector<const char*> msgKey = {"file", "reason"}; \ const std::vector<const char*> msgValue = {file, reason}; \ OP_LOGE_WITHOUT_REPORT("EZ1004", "%s", msg.c_str()); \ REPORT_PREDEFINED_ERR_MSG("EZ1004", msgKey, msgValue); \ } while (false) #define OP_LOGE_FOR_FILE_OPERATION_ERROR_PARSE_WITH_INVALID_CONTENT(file, reason) \ do { \ std::string msg = std::string("Failed to parse file ") + file + \ ". Reason: " + reason + "."; \ const std::vector<const char*> msgKey = {"file", "reason"}; \ const std::vector<const char*> msgValue = {file, reason}; \ OP_LOGE_WITHOUT_REPORT("EZ1005", "%s", msg.c_str()); \ REPORT_PREDEFINED_ERR_MSG("EZ1005", msgKey, msgValue); \ } while (false)可以看到,框架在抛出错误时不仅通过OP_LOGE_WITHOUT_REPORT写入错误日志,还通过REPORT_PREDEFINED_ERR_MSG将file与reason作为键值对上报,便于上层错误管理系统(如 plog / 错误码采集)将日志与结构化错误码关联。
三、典型报错实例逐字解读
官方文档给出了一个 EZ1004 的完整报错示例:
Failed to parse file /home/developer/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe//kernel/ascendxxxx/ops_legacy/add/Add_41dadce325b0f810d03359af2a38990b_high_performance.json. Reason: [json.exception.parse_error.101] parse error at line 4, column 14: syntax error while parsing object - unexpected string literal; expected '}'.对这条报错可以拆解为三层信息:
| 信息片段 | 含义 |
|---|---|
/home/developer/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe//kernel/ascendxxxx/ops_legacy/add/Add_..._high_performance.json | 出错的内置算子 kernel 描述文件,位于 CANN 安装目录 opp 包中,是 Add 算子的_high_performance变体 JSON |
[json.exception.parse_error.101] | nlohmann/json 库的解析异常编号 101,属于"语法错误"类别 |
parse error at line 4, column 14: syntax error while parsing object - unexpected string literal; expected '}' | 具体位置与原因:文件第 4 行第 14 列,在解析对象时遇到了意外的字符串字面量,期望的是}。典型场景是键值对之间缺少逗号、结尾多写了逗号、引号未闭合或括号不匹配 |
parse_error.101是 nlohmann/json 的标准错误类型,几乎可以断定问题出在 JSON 文件本身的语法层面,而非框架逻辑。此类错误常见诱因包括:文件在传输/拷贝过程中被截断、被文本编辑器或脚本意外改写了格式、多字节字符编码损坏、以及人为手工编辑后未做格式校验。
EZ1005 的官方示例则展示了另一类问题:
Failed to parse file /home/developer/Ascend/cann-9.0.0/opp/built-in/op_impl/ai_core/tbe/config/ascendxxx/aic-ascendxxxx-ops-info-oam.json. Reason: The operator JSON file is not in the standard key-value structure.这里的Reason不再是解析器异常,而是框架自定义的校验提示:"算子 JSON 文件不是标准的键值结构"。也就是说文件本身是合法 JSON,但顶层结构不符合框架约定的对象(key-value)形态,导致merge_patch或后续字段访问失败。
四、源码级成因:EZ1004/EZ1005 究竟在哪些环节触发
通过检索仓库中所有调用宏的位置,可以勾勒出该错误码的完整触发链路。框架对算子 kernel 相关 JSON 的解析主要集中在复合算子引擎(composite_op)与单算子执行器(individual_op)两条路径。
4.1 kernel 库 JSON 合并解析(最典型场景,与官方示例完全对应)
src/nnopbase/composite_op/aclnn_engine/op_kernel_lib.cpp 中的OpKernelLib::Initialize()是官方示例中该类报错的核心出处:
for (const auto& filePath : opKernelLibFilePaths) { OP_LOGI("OpKernelLib start parse json file: %s.", filePath.c_str()); try { std::ifstream f(filePath); allKernelsJson_.merge_patch(Json::parse(f)); OP_CHECK(allKernelsJson_.is_object(), OP_LOGE_FOR_FILE_OPERATION_ERROR_PARSE_WITH_INVALID_CONTENT( filePath.c_str(), "The operator JSON file is not in the standard key-value structure"), return ACLNN_ERR_INNER_LOAD_JSON_FAILED); } catch (std::exception& e) { OP_LOGE_FOR_FILE_OPERATION_ERROR_PARSE(filePath.c_str(), e.what()); return ACLNN_ERR_INNER_LOAD_JSON_FAILED; } }这段代码揭示了两层触发逻辑:
Json::parse(f)抛出异常(如json.exception.parse_error.101)时,异常信息e.what()被原样作为Reason,走EZ1004上报;- 文件解析成功但顶层不是 JSON 对象时,抛出框架自定义原因
The operator JSON file is not in the standard key-value structure,走EZ1005上报。
加载顺序为:自定义算子包(custom opp)> vendors 算子包 > 内置算子包(built-in),并且框架会对所有同名 JSON 做merge_patch合并,这意味着任意一个包的 JSON 语法损坏,都可能中断整个 kernel 库的初始化,返回ACLNN_ERR_INNER_LOAD_JSON_FAILED。
4.2 单个 kernel 二进制的 JSON 校验
在 src/nnopbase/composite_op/aclnn_engine/op_kernel.cpp 中还有两处典型触发点:
- 二进制数据读取失败时,将
errno与系统错误文本拼成 Reason 走 EZ1004(op_kernel.cpp); - 非 fat-bin 场景下,JSON 中缺少必需的
kernelName字段时,抛出自定义原因The operator JSON file does not contain the kernel name,走 EZ1005(op_kernel.cpp)。由此可以推断:EZ1005 不仅用于"非标准结构",也用于"缺少必需字段"的内容校验。
4.3 单算子(individual op)执行路径
单算子执行框架同样复用了这两个宏:
- src/nnopbase/individual_op/executor/indv_executor.cpp:单算子二进制信息解析失败;
- src/nnopbase/individual_op/executor/indv_bininfo.cpp:bininfo 解析失败;
- src/nnopbase/individual_op/executor/indv_collector.cpp:解析
binary_info_config.json失败,并携带 OPP 包相关的原因常量。
另外,复合算子引擎中 src/nnopbase/composite_op/aclnn_engine/kernel_mgr.cpp 在解析 kernel 管理 JSON 时同样会走 EZ1004。这说明EZ1004 覆盖了框架内所有"读取并解析算子相关 JSON/二进制"的公共入口,而 EZ1005 则专门用于内容/结构/字段级的语义校验失败。
五、排查与恢复实践
结合官方文档给出的 Solution("按 Reason 中的提示定位问题,提供正确的文件")与 EZ1005 的恢复建议(重装自定义/内置算子包),完整的排查流程建议如下:
读透 Reason,二分定位:
- Reason 以
[json.exception.*]开头 → JSON 语法层错误(EZ1004); - Reason 为
not in the standard key-value structure、does not contain the kernel name等 → 内容/结构层错误(EZ1005); - Reason 包含
[Errno N]→ 文件读取层错误(EZ1004,常见于权限、文件缺失)。
- Reason 以
按报错中的文件路径检查文件是否存在:对照报错中的完整路径,确认文件确实存在于该位置,并检查读写权限与文件大小是否异常(0 字节或明显被截断多半是安装/拷贝失败)。
校验 JSON 语法:将报错中给出的文件拷贝出来,用任意 JSON 校验工具或脚本检查。若报错给出行列号(如
line 4, column 14),直接定位到对应行,重点检查括号匹配、逗号缺失、引号与转义字符。修复后应恢复原始文件内容,而不是依赖框架的merge_patch容错。区分自定义包与内置包,选择性重装:EZ1005 的官方建议是分别重装自定义算子包或内置算子包。仓库在加载时对 custom opp、vendors、built-in 三部分做优先级合并,因此可先通过报错路径判断归属:
- 路径含
custom或自定义安装目录 → 重装自定义算子包(scripts/package/opbase/scripts/opp_custom_install.sh 等安装脚本可参考); - 路径含
opp/built-in(如官方示例)→ 重装内置算子包(opp 包)。
- 路径含
回归验证:修复或重装后,重新执行算子编译/运行流程,确认不再出现
Failed to parse file ...且算子 kernel 库成功初始化(正常时日志会出现Successfully initialized op kernel library,见 op_kernel_lib.cpp)。收集现场证据:如果问题持续,保留完整报错文本、出错 JSON 文件、以及出错时刻的 plog 日志,供 CANN 技术支持定位。
六、如何从源头规避这类错误
仓库测试目录中存放了大量算子 kernel 的 JSON 样例(如 tests/nnopbase/mock/built-in/op_impl 下的 mock 数据,以及 tests/nnopbase/mock/static_kernel/ai_core 下的静态 kernel 测试 JSON),可供核对标准结构。在开发与交付阶段建议:
- 开发期引入格式校验门禁:算子 JSON 生成后先做语法与 schema 校验再打包;
- 交付期避免手工编辑:内置包交付前走完整构建流程,自定义包交付前用官方提供的校验工具核对;
- 运行期关注环境完整性:安装、升级、覆盖安装后核对 opp 目录文件数量与校验和,避免出现半截文件或旧版本残留文件被错误解析。
七、与相邻错误码的区分
| 错误码 | errTitle | 典型 Reason 形态 | 适用阶段 |
|---|---|---|---|
| EZ1003 | File_Operation_Error_Open | 打开文件失败(路径/权限) | 文件访问层 |
| EZ1004 | File_Operation_Error_Parse | 解析器异常(JSON 语法错误等) | 文件解析层 |
| EZ1005 | File_Operation_Error_Parse | 内容非标准键值结构、缺少必需字段 | 文件内容校验层 |
| EZ0031 | File_Operation_Error_Parse | AIPP 等算子配置项缺失 | 算子开发/配置阶段 |
一句话总结:EZ1004 是"文件读得进但解析器报错",EZ1005 是"文件能解析但内容不合规"。排查时先读Reason关键字,再对照报错文件路径决定是修复文件内容、重新生成配置,还是重装对应算子包,即可快速收敛问题。
参考文档
- EZ1004 官方错误说明
- EZ1005 官方错误说明
- Nnopbase-Errors 错误码索引
- EZ0031 算子侧文件解析错误
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考