Skip to content

celEngine 的 classifyError 把「括号/方括号不配对」这类真语法错答成 kind: 'runtime',而该 kind 会原样出现在作者可见的拒写消息与 REST 响应体里 #6133

Description

@baozhoutao

范围外发现,出自 #4812 / PR #6130 的对拍测试(一条 fixture 断言 kind === 'parse' 意外翻红)。按 Prime Directive #10 记录,不指派。

事实(origin/main bc67c28e2 基线,实测)

packages/formula/src/cel-engine.tsclassifyError错误文案关键词分类:

function classifyError(err: unknown): EvalResult<never> {
  const message = err instanceof Error ? err.message : String(err);
  let kind: 'parse' | 'type' | 'runtime' | 'bounds' = 'runtime';
  if (/Exceeded max/i.test(message)) kind = 'bounds';
  else if (/parse|unexpected|syntax/i.test(message)) kind = 'parse';
  else if (/type|unknown variable|undeclared/i.test(message)) kind = 'type';
  return { ok: false, error: { kind, message } };
}

而 cel-js 8.0.0 对语法错并不只有一种措辞。实测五条:

源码 cel-js 首行错误 命中分支 得到的 kind
record.budget > Unexpected token: EOF unexpected parse
record.a $$ 1 Unexpected character: $ unexpected parse
record.a ?? 3 Unexpected token: QUESTION unexpected parse
((record.a) Expected RPAREN, got EOF runtime
[1,2 Expected RBRACKET, got EOF runtime

Expected RPAREN, got EOF 里既没有 parse / unexpected / syntax,也没有 type / unknown variable / undeclared,于是落到默认值 runtime括号、方括号、花括号不配对是最常见的手写语法错之一,恰好整类都落在这个洞里。

为什么这条是用户可见的(不是纯内部字段)

kind 不止用于内部分支,它被原样拼进作者读到的文案和 API 响应体:

  • packages/objectql/src/validation/rule-validator.ts:1262
    `Validation rule '${rule.name}' predicate failed to evaluate (${result.error.kind}: ${result.error.message}) — write rejected (#4649)`
  • 同文件 :1417,when-predicate 版本同构
  • packages/objectql/src/cel-fault.ts:75
    return `${error.kind}: ${first || 'unknown error'}`;
  • packages/rest/src/rest-server.ts:571
    ...(error?.kind ? { reason: error.kind } : {}) —— 进 HTTP 错误响应的 reason 字段

所以一条少写了一个右括号的校验规则,作者拿到的是 (runtime: Expected RPAREN, got EOF),REST 消费方拿到的是 reason: "runtime"。message 本身是对的,分类是错的 —— 而分类正是用来告诉作者"这该去哪儿修"的:runtime 指向数据/求值期,parse 指向"你的表达式写错了"。ADR-0032 D1d 要求消息面向自纠,这一格与之相悖。

影响面

classifyError 同时服务 celEngine.compilecelEngine.evaluate,所以 build 期(os build / os validate / os lint)与运行期(写入拒绝、REST)两侧都受影响

未量化 / 未主张

  • 没有统计真实 metadata 里不配对分隔符的出现频率。
  • 没有排查 cel-js 是否还有别的语法错措辞同样漏网(上表只穷举了我构造的五条);这个洞的成因是"靠文案关键词分类"这个做法本身,补关键词只是补当前已知的洞。

建议方向(供 triage,不代裁)

关键词匹配是脆的:cel-js 换一次措辞就再破一次。可考虑改读 cel-js 抛出的错误对象上的结构化信息(ErrorOptionscode,见 lib/index.d.ts:82-86),把分类建立在契约上而不是文案上;若结构化信息不足以区分,则至少把关键词表补全并加一组 fixture 钉住每一类措辞 —— 后者是止血,前者是根治。

关联

#4812 / PR #6130(发现出处;该 PR 的对拍测试里刻意没有把这条错误分类断言进去,并在注释里写明了原因 —— 断言它等于把这个 bug 钉成契约)。ADR-0032 D1d(自纠消息)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions