news 2026/9/19 18:06:57

CANN Runtime 错误码 EE1003 Invalid_Argument 深度解析:从报错格式到源码排查实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN Runtime 错误码 EE1003 Invalid_Argument 深度解析:从报错格式到源码排查实战

CANN Runtime 错误码 EE1003 Invalid_Argument 深度解析:从报错格式到源码排查实战

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

导读:EE1003 是 CANN Runtime(RTS)对外暴露的“参数非法(Invalid Argument)”错误码,用于在运行时接口收到超出合法范围的输入参数时给出统一的、带四段式结构化信息的报错。本文以官方错误码参考文档为主体,结合cann/runtime仓库中的错误码定义表(src/dfx/error_manager/error_code.json)、RTS 接口声明(pkg_inc/runtime/runtime/rts/rts_stream.h)以及错误码上报宏实现(src/runtime/core/inc/base.hppsrc/runtime/core/inc/common/error_message_manage.hpp)进行纵深解读,帮助开发者准确读懂 EE1003 报错信息、快速定位非法参数根因,并掌握参数范围校验与接口调用关系的排查方法。

1. EE1003 是什么:RTS 错误码家族中的“参数校验哨兵”

CANN Runtime 在运行过程中会通过统一的错误码体系向 Host 侧上报异常,错误码以EE前缀标识 Execution Error(执行类错误)。在docs/en/error_code_ref/RTS-Errors/目录下,围绕同一类问题往往有多个细分错误码,例如:

  • EE1001Invalid_Argument:参数无效,报错格式为The argument is invalid. Reason: %s,通过附加信息说明原因;
  • EE1003Invalid_Argument:参数值非法(本文主题),报错中直接给出非法参数值、参数名与期望值;
  • EE1004Invalid_Argument_Null_Pointer:参数为空指针,报错格式为%s failed because %s cannot be a NULL pointer.
  • EE1005Not_Supported:当前系统或设备不支持该功能。

其中 EE1003 的特点在于报错信息自带“回放”能力——它把出错的函数、传入的非法值、参数名以及期望值四项关键信息全部嵌入错误文本,开发者无需额外的上下文即可判断是哪一次调用、哪个参数、传了什么值、应该传什么值。

在仓库的错误码定义表 src/dfx/error_manager/error_code.json 中,EE1003 的登记信息如下:

{ "errClass": "RTS Errors", "errTitle": "Invalid_Argument", "ErrCode": "EE1003", "ErrMessage": "%s failed because value %s for parameter %s is invalid. Expected value: %s.", "Arglist": "func, value, param, expect", "suggestion": { "Possible Cause": "N/A", "Solution": "1. Check the input parameter range of the function. 2. Check the function invocation relationship." } }

这里ErrMessage中的四个%s占位符与Arglist中的func, value, param, expect一一对应,构成了 EE1003 报错的固定模板,也是本文第 2 节将详细拆解的格式来源。

2. 读懂 EE1003 的报错格式:四个占位符的含义

根据官方错误码参考文档(EE1003-Invalid_Argument.md),EE1003 的报错模板为:

%s failed because value %s for parameter %s is invalid. Expected value: %s.

其中各占位符%s的语义按出现顺序依次为:

序号占位符含义示例
1%s报错阶段(Error stage)或发起调用的 API 名称rtsStreamSetAttribute
2%s传入的非法参数值(Parameter value)-5
3%s参数名(Parameter name)stmAttrId
4%s期望值(Expected value),即该参数的合法取值范围[0, 5)

文档给出的完整报错示例如下:

rtsStreamSetAttribute failed because value -5 for parameter stmAttrId is invalid. Expected value: [0, 5).

逐段解读这行报错

  1. 报错发生在rtsStreamSetAttribute接口调用中;
  2. 开发者向该接口的stmAttrId(Stream 属性 ID)参数传入了-5
  3. -5不在stmAttrId的合法取值区间[0, 5)内,因此接口校验失败并返回错误。

说明:报错示例中的期望值[0, 5)是演示用区间,用于展示“区间/范围”类期望值的写法(左闭右开)。实际合法范围以当前版本的头文件与接口校验逻辑为准——例如当前仓库 pkg_inc/runtime/runtime/rts/rts_stream.h 中rtStreamAttr枚举的合法值为 1~6(详见第 4 节),不同版本、不同 SoC 上的合法范围可能不同。期望值也可能以(a, b][a, b]>= x、枚举名列表等其它形式呈现。

3. 从源码看 EE1003 是如何被“拼装”出来的

EE1003 的报错文本并非由各接口自行printf,而是由 Runtime 的错误上报宏统一生成。理解这条链路,有助于你反推“报错里的每个字段到底从哪来”。

3.1 核心上报宏

在 src/runtime/core/inc/base.hpp 中定义了 EE1003 专用的上报宏:

// EE1003错误码上报 #define RT_LOG_OUTER_MSG_INVALID_PARAM(parm, ...) \ RT_LOG_OUTER_MSG_WITH_FUNC(ErrorCode::EE1003, (parm), #parm, ##__VA_ARGS__)

其作用是把错误码EE1003、当前函数名(通过__func__注入,见RT_LOG_OUTER_MSG_WITH_FUNC)以及参数名(通过#parm字符串化)组合成一次错误上报。继续追踪RT_LOG_OUTER_MSG_IMPL(同样位于 base.hpp):

#define RT_LOG_OUTER_MSG_WITH_FUNC(error_code, ...) RT_LOG_OUTER_MSG_IMPL((error_code), __func__, ##__VA_ARGS__) #define RT_LOG_OUTER_MSG_IMPL(error_code, ...) \ do { \ ErrorCodeProcess((error_code), __FILE__, __LINE__, &__func__ [0], { RT_ERRVAL_VALUES(__VA_ARGS__) }); \ } while (false)

ErrorCodeProcess内部(base.hpp 第 280 行附近)会进一步调用ProcessErrorCodeImplErrorManager::GetInstance().ATCReportErrMessage(...),将错误码文本与参数值一起上报给错误管理模块(ErrorManager),最终以文档第 2 节所述模板输出。可见:

  • 报错阶段/API 名(第 1 个 %s)= 出错处所在函数的__func__
  • 参数名(第 3 个 %s)= 宏中#parm字符串化后的源码参数名;
  • 参数值(第 2 个 %s)= 宏调用时显式传入的可读值表达式,通常用ToString(var)之类的转换得到;
  • 期望值(第 4 个 %s)= 宏的可变参数部分追加传入。

3.2 配合条件判断的“判参即上报”宏

在 src/runtime/core/inc/common/error_message_manage.hpp 中,还封装了“条件不满足 → 上报 EE1003 → 返回错误码”的惯用宏:

// EE1003错误码使用,value与参数名分开传入 #define COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME(COND, RTERRCODE, value, paramName, ...) \ if (unlikely((COND))) { \ RT_LOG_OUTER_MSG_WITH_FUNC(ErrorCode::EE1003, (value), (paramName), ##__VA_ARGS__); \ return (RTERRCODE); \ }

该宏的注释明确说明了两个实参的约定:

  • value:可读值表达式(运行时求值),如ToString(var)
  • paramName:参数名的字符串字面量(如"level""flag")。

从源码结构可以推断:Runtime 各接口在校验输入时,若发现参数超出合法区间,会优先走这套宏组合,从而保证同一错误码(EE1003)的报错格式在全仓库范围内完全一致——这正是错误码参考文档能用一个统一模板覆盖所有场景的原因。

4. 以示例接口rtsStreamSetAttribute为例:参数范围到底怎么查

EE1003 报错示例中出现的是rtsStreamSetAttribute,这是 RTS 层(pkg_inc/runtime/runtime/rts/)提供的 Stream 属性设置接口。查看其声明 pkg_inc/runtime/runtime/rts/rts_stream.h:

/** * @ingroup dvrt_stream * @brief set stream attribute * @param [in] stm stream handle * @param [in] stmAttrId stream attribute id * @param [in] attrValue stream attribute value * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API RT_DEPRECATED_MESSAGE(RT_RUNTIME_DEPRECATED_MESSAGE) rtError_t rtsStreamSetAttribute(rtStream_t stm, rtStreamAttr stmAttrId, rtStreamAttrValue_t* attrValue);

注意接口返回值的注释:成功返回RT_ERROR_NONE,参数错误返回RT_ERROR_INVALID_VALUE——这与 EE1003 的“非法值”定位一致。下面拆解stmAttrId的合法范围。

4.1 参数类型:rtStreamAttr枚举

stmAttrId的类型rtStreamAttr在 rts_stream.h 中定义:

typedef enum { RT_STREAM_ATTR_FAILURE_MODE = 1, // 遇错模式(继续执行 / 遇错即停) RT_STREAM_ATTR_FLOAT_OVERFLOW_CHECK = 2, // 浮点溢出检查开关 RT_STREAM_ATTR_USER_CUSTOM_TAG = 3, // 用户自定义标签 RT_STREAM_ATTR_CACHE_OP_INFO = 4, // 算子缓存信息开关 RT_STREAM_ATTR_PRIORITY = 5, // Stream 优先级 RT_STREAM_ATTR_LAUNCH_BLOCKING_MODE = 6, // Launch 阻塞模式 RT_STREAM_ATTR_MAX = 7, // 哨兵值:属性总数 } rtStreamAttr;

因此当前仓库中stmAttrId的合法取值为枚举成员 1~6RT_STREAM_ATTR_MAX是用于表示“属性个数/上限”的哨兵值,不应作为合法属性 ID 传入。

4.2 参数类型:rtStreamAttrValue_t联合体

attrValue的类型rtStreamAttrValue_t是一个联合体,不同属性复用同一块存储,按属性类型解释:

typedef union { uint64_t failureMode; // RT_STREAM_ATTR_FAILURE_MODE:0=继续执行,1=遇错即停 uint32_t overflowSwitch; // RT_STREAM_ATTR_FLOAT_OVERFLOW_CHECK uint32_t userCustomTag; // RT_STREAM_ATTR_USER_CUSTOM_TAG uint32_t cacheOpInfoSwitch;// RT_STREAM_ATTR_CACHE_OP_INFO uint32_t streamPriority; // RT_STREAM_ATTR_PRIORITY uint32_t launchBlockingMode;// RT_STREAM_ATTR_LAUNCH_BLOCKING_MODE uint32_t rsv[4]; } rtStreamAttrValue_t;

例如RT_STREAM_ATTR_FAILURE_MODE的取值可参考同一头文件中的宏定义:

#define RT_STREAM_FAILURE_MODE_CONTINUE_ON_FAILURE (0x0U) // 默认值,task出错时处理完异常后继续执行流上的任务 #define RT_STREAM_FAILURE_MODE_STOP_ON_FAILURE (0x1U) // 遇错即停

4.3 排查思路的落地

对照上述头文件,报错示例中stmAttrId被传入-5:该值既不是rtStreamAttr枚举中的任何成员,也不在 1~6 的取值范围内,接口在校验阶段即判定非法,从而触发 EE1003 上报。这直观展示了“检查接口输入参数范围”在实践中的做法——以头文件中的枚举定义、宏定义、以及接口注释中标注的取值范围为准,而不是凭经验猜值

5. 官方解决方法逐条展开:两步定位 EE1003

官方参考文档给出的解决方法是两条:

  1. Check the input parameter range of the function.(检查接口的输入参数范围)
  2. Check the function invocation relationship.(检查接口的调用关系)

下面结合仓库实际展开这两步。

5.1 第一步:核对接口输入参数范围

这是 EE1003 的首要排查方向,因为报错本身已经明确告诉了你“哪个参数、什么值、期望什么”。排查建议:

  1. 读报错中的参数名与期望值:报错第 3、4 段已经给出了参数名和合法范围,直接对比即可确认是否为“值越界”;
  2. 回查头文件中的枚举/宏定义:对于枚举类型参数,核对传入值是否为枚举成员(参考第 4.1 节的rtStreamAttr);对于布尔开关,核对是否为 0/1(如 rts_stream.h 中的RT_STREAM_FAILURE_MODE_*RT_STREAM_LAUNCH_BLOCKING_MODE_*等宏);
  3. 确认传参类型与接口签名一致:注意rtStreamAttrValue_t是联合体,若按错误的成员类型赋值(例如给uint64_t字段填入超过uint32_t的值),也可能触发校验失败;
  4. 关注接口注释的返回值说明:如rtsStreamSetAttribute注释所示,非法输入会返回RT_ERROR_INVALID_VALUE,与 EE1003 语义一致。

5.2 第二步:检查接口的调用关系

当“传入值本身合法、但仍报 EE1003”时,问题往往出在调用上下文而非参数值本身。典型场景包括:

  • 接口未初始化前置依赖:例如在 Stream 创建/上下文绑定完成之前就调用属性设置接口,导致接口内部校验到流句柄或上下文状态异常,间接以参数非法形式返回;
  • 多线程/多 Device 场景下的参数串扰:调用方在不同线程间复用了同一参数缓存或未初始化内存(如attrValue指向的联合体未被正确赋值),读出的“参数值”不可预期;
  • 版本能力差异:某些属性或取值仅在特定 SoC(如 Arch 版本)上支持,跨版本复用参数可能导致校验失败——仓库中runtime_api_stub_catalog.defarch5162_unsupported_runtime_api.def等文件的存在,说明不同芯片架构对外暴露的 Runtime API 集合存在差异,这是排查时值得留意的一点。

此时建议梳理从应用入口到出错接口的完整调用链(初始化 → Device/Context 绑定 → Stream 创建 → 属性设置),确认每一环的返回值与调用顺序是否符合接口文档要求。

6. EE1003 与相邻错误码的区分与联动

排查 EE1003 时,常常会遇到“报错相似但错误码不同”的情况,区分它们有助于快速收敛方向:

错误码标题报错模板典型触发场景
EE1001Invalid_ArgumentThe argument is invalid. Reason: %s参数语义不合法,原因以附加信息给出
EE1003Invalid_Argument%s failed because value %s for parameter %s is invalid. Expected value: %s.参数值超出合法范围(本文主题)
EE1004Invalid_Argument_Null_Pointer%s failed because %s cannot be a NULL pointer.指针参数为空,参见 EE1004 文档
EE1005Not_SupportedThe current system or device does not support %s.当前系统/设备不支持某功能

以上模板均可从 error_code.json 的ErrMessage字段逐一核对。简化的判断口诀:

  • 报错里出现非法值 + 期望值→ EE1003;
  • 报错里只提空指针→ EE1004;
  • 报错里说明设备不支持→ EE1005;
  • 报错里仅给出通用原因描述→ EE1001。

7. 快速自查清单(FAQ 式小结)

Q1:EE1003 报错中的“期望值 [0, 5)”是全局统一的范围吗?不是。期望值由具体接口及其所在版本的校验逻辑决定,报错示例中的[0, 5)仅用于演示格式。实际范围请以当前版本的头文件枚举、宏定义与接口文档为准。

Q2:报错里的函数名一定是我调用的那个 API 吗?通常是。EE1003 模板第 1 个%s由上报宏自动填充当前函数名(__func__),即错误发生处所属的接口;如果你的代码直接调用了该接口,那么它就是报错者;如果是间接调用,则需要沿调用链回溯。

Q3:为什么参数明明“看起来合法”还是会报 EE1003?优先按第 5.2 节检查调用关系与上下文状态(初始化、Device/Context 绑定、并发与版本能力差异),并确认传给接口的参数对象(尤其是指针指向的联合体/结构体)确实被正确初始化。

Q4:EE1003 与 EE1004 有什么区别?EE1004 专用于空指针参数(模板含cannot be a NULL pointer);EE1003 用于非空但值越界的参数。两者同属 RTS Errors 的 Invalid_Argument 类别,可对照 RTS 错误码总览 查看完整家族。

8. 结语

EE1003 是 CANN Runtime 对外输出“参数非法”信息的标准化通道:一方面,它以固定模板承载了函数名、非法值、参数名、期望值四要素,让报错信息本身具备极强的自解释性;另一方面,仓库在 error_code.json、base.hpp、error_message_manage.hpp 中的实现保证了全仓库错误文本格式统一、可被日志与上层工具稳定解析。遇到 EE1003 时,先读清四段式报错内容,再对照对应接口头文件的枚举与宏定义核查参数范围,最后审视调用关系与上下文状态,即可快速定位并消除问题。

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

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

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

N_m3u8DL-RE 使用指南:下载、解密、直播录制一次讲清

N_m3u8DL-RE 使用指南:下载、解密、直播录制一次讲清 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE …

作者头像 李华
网站建设 2026/9/19 18:04:58

智能客户数据平台在AWS的落地实践:架构、身份解析与成本治理

简介:这是一份聚焦智能客户数据平台(CDP)云端落地的解决方案型PPT资源,面向企业架构师、数据产品经理及营销技术从业者,系统解析基于AWS构建客户数据管理平台的整体思路。内容从CDP概念入手,梳理企业724小时…

作者头像 李华
网站建设 2026/9/19 18:04:12

把 Claude Code 的 ANTHROPIC_BASE_URL 改到 TaoToken,MacBook M1 装完再跑 claude

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

作者头像 李华
网站建设 2026/9/19 18:04:04

程序员必藏:130个开发效率网站与开源资源全盘点

写代码写了十年,我越来越确定一件事:决定一个程序员能走多远的,往往不是他敲代码的速度,而是他会不会用工具、会不会找资源、会不会站在别人的肩膀上干活。刚入行那会儿,我总觉得“技术人就得什么都自己造轮子”&#…

作者头像 李华
网站建设 2026/9/19 18:03:30

C++手写数据挖掘系统:Apriori、FCM与ID3全流程实现

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

作者头像 李华