# 错误处理流程 sap-cli 命令失败时的标准处理流程。严格按顺序执行。 ## 通用流程 ``` 命令失败 ↓ 1. 诊断根因(使用方式错误 or 代码/环境问题?) ↓ 2. 使用方式错误 → 修正参数后重试 ↓ 3. sap-cli 限制 → 报告失败,不绕过 ↓ 4. SAP 系统限制 → 穷尽自动化方案 ↓ 5. 确认无法自动化 → 请求用户 SAP GUI 操作 ``` ## 步骤 1:诊断根因 检查以下项目: | 检查项 | 方法 | |--------|------| | 命令参数是否正确 | 对照 `python main.py --help` 和 SKILL.md 验证参数 | | 文件是否存在、内容是否为空 | `cat` 或 `ls` 检查 | | 传输请求号是否正确 | `python main.py transport info --corr_nr DEVK901XXX` | | 网络连接是否正常 | `python main.py config show` 验证配置 | | 对象是否存在于 SAP | `python main.py info --name XXX --type class` | ## 步骤 2:使用方式错误 修正后重试。常见修正: - 缺少 `--corr_nr` → 加上传输请求号 - 对象名大小写错误 → sap-cli 会自动处理,但路径要注意 - 文件路径错误 → 检查相对/绝对路径 - 对象类型不匹配 → 用 `python main.py --help` 确认支持的类型 ## 步骤 3:sap-cli 限制 如果确认不是使用方式问题,**如实报告错误信息**,不要尝试绕过 sap-cli: ``` ❌ 错误做法:写 Python requests 脚本绕过 ❌ 错误做法:用 curl 直接调 ADT 端点 ❌ 错误做法:导入 ADTClient 调内部方法 ✅ 正确做法:报告失败,说明原因 ``` ## 步骤 4:穷尽自动化方案(SAP 系统限制时) 遇到 SAP 系统限制时,按以下顺序穷尽自动化方案: ### 方案 A:调整 sap-cli 参数重试 - 尝试不同的 `--corr_nr` - 尝试 `--dry-run` 预览后执行 - 检查是否有残留锁(`show-table` 查看 SM12 相关信息) ### 方案 B:ABAP 报表 workaround 通过 `run-program` 执行辅助报表: ```bash # 清除残留锁 python main.py sync --type report --name ZSAPILOT_CLEAR_LOCKS --path --corr_nr DEVK901XXX python main.py run-program --name ZSAPILOT_CLEAR_LOCKS ``` ### 方案 C:delete + recreate 如果对象需要完全重写: ```bash python main.py delete --name ZMY_CLASS --type class python main.py sync --name ZMY_CLASS --type class --path --corr_nr DEVK901XXX ``` 注意:delete 可能因传输请求绑定而失败(HTTP 423),此时需要用户在 SE09 操作。 ### 方案 D:activate 单独重试 ```bash python main.py activate --name ZMY_CLASS --type class --corr_nr DEVK901XXX ``` NW 7.40 的 double-activate 已内置在 sap-cli 中。如果 activate 仍然失败,**不要再尝试其他激活策略**,直接报告给用户。 ## 步骤 5:请求用户 SAP GUI 操作 **只在确认所有自动化方案穷尽后**才请求用户操作。 ### 必须一次性给出完整操作清单 当需要用户在 SAP GUI 操作时,**绝不能渐进式发现问题**: - ❌ 错误:先让用户加字段 A,测试后发现缺字段 B,又让用户加字段 B - ✅ 正确:先做全面对比分析(`show-table` vs 代码中的字段引用),一次性给出完整变更清单 ### 系统表操作的 4 步授权流程 如果需要操作系统表(唯一的例外情况): 1. **解释原因** — 为什么需要操作系统表 2. **列出具体操作** — 表名 + 操作类型(如 `DELETE FROM SEOCLASS WHERE ...`) 3. **说明风险和替代方案** — 可能的副作用、有没有不操作系统表的替代方案 4. **等待用户确认** — 得到明确授权后才执行 ## 常见失败场景速查 | 错误 | 常见原因 | 处理方式 | |------|----------|----------| | HTTP 406 (info 查 DDIC) | NW 7.40 不支持 DDIC 专属媒体类型;`application/xml` 同样 406,只有 `*/*` 可用 | 工具已内置 `*/*` 回退,无需手工处理 | | HTTP 406 (Lock DDIC) | NW 7.40 不支持 DDIC 对象 ADT Lock | 报告用户,SE09 处理 | | HTTP 403 (Locked) | 残留 enqueue lock | 先尝试 `run-program` 清锁报表,不行才 SM12 | | HTTP 400 (SaveFailure) | 类 DEFINITION 与 SAP 不一致 | 检查本地 vs SAP 的 DEFINITION 差异 | | HTTP 423 (Transport lock) | 对象绑定在传输请求中 | 报告用户,SE09 处理 | | 激活失败仍 inactive | NW 7.40 ADT 限制 | sap-cli 已内置 double-activate,仍失败则报告用户去 SE09 | | `WITH EMPTY KEY` 运行 dump | NW 7.40 不支持 | 修改为 `WITH NON-UNIQUE KEY` 或 `WITH DEFAULT KEY` | | HTTP 400 (Data Preview) `A Boolean expression was expected in <字段>=` | ADT Data Preview freestyle SQL **不支持 `=` 比较**(实测:`WHERE f='x'`→400,`WHERE f IN ('x')`→200) | 改用 `IN (...)` 或 `LIKE '...'`,不要用 `=` | | HTTP 400 (Data Preview) `elements in the SELECT LIST list must be separated using commas` | 选择列必须逗号分隔(`SELECT a b` 报错) | 写成 `SELECT a, b FROM t` | | `info` 的「传输请求」恒为 `(无法获取)` | `_query_transport_request` 用 `=` + 单引号查 E071,在该方言下必然 400(异常被吞,故静默失败) | 改为 `WHERE object IN ('...') AND obj_name IN ('...')` | ## ADT Data Preview SQL 方言(NW 7.40 实测,2026-09-11) 用于补 ZMM_BIP 系列等元数据时,本系统 `/sap/bc/adt/datapreview/freestyle` 的 SQL 解析器只接受很窄的子集: | 能力 | 实测结果 | |------|----------| | `SELECT f1, f2 FROM t`(逗号分隔) | ✅ 200 | | `WHERE f IN ('a','b')` | ✅ 200 | | `WHERE f LIKE 'ZMM%'` | ✅ 200 | | `WHERE f = 'a'` | ❌ 400 `A Boolean expression was expected` | | `SELECT f1 f2`(无逗号) | ❌ 400 要求逗号分隔 | | 无 WHERE 全表 | ✅ 200(但行数受行数参数与授权限制) | **可用的元数据来源(本机实测)**: | 对象类型 | 描述表(键, 语言, 文本) | 开发包来源 | |----------|--------------------------|------------| | 结构 / 表 | `DD02T`(`TABNAME`/`DDLANGUAGE`/`DDTEXT`) | `TADIR`(`OBJECT='TABL'`) | | 表类型 | `DD40T`(`TYPENAME`/`DDLANGUAGE`/`DDTEXT`) | `TADIR`(`OBJECT='TTYP'`) | | 数据元素 | `DD04T`(`ROLLNAME`/`DDLANGUAGE`/`DDTEXT`) | `TADIR`(`OBJECT='DTEL'`) | | 域 | `DD01T`(`DOMNAME`/`DDLANGUAGE`/`DDTEXT`) | `TADIR`(`OBJECT='DOMA'`) | | 类 | ADT 已直接提供 | `TADIR`(`OBJECT='CLAS'`) | - 描述文本的语言不统一:同一批 ZMM_BIP 结构里有的只有 `DDLANGUAGE='1'`,有的只有 `'E'`;补全时必须按「登录语言 → `E` → `1` → 首行」回退,不能硬取一种。 - **ZMM_BIP 系列 9 个 DDIC 对象在 `TADIR` 里查不到任何行**(结构与表类型均无注册)→ 无法从系统取得开发包,也意味着未登记对象目录(传输/对象清单角度需注意)。