Skip to content

[finding] queryDataset 里还有第二个 message 嗅探器 isMissingSourceError,命中即静默返回空结果 —— dataset-compiler 的一条拒收措辞已经命中它,只因抛点在 try 之外才没出事 #5717

Closed

Description

@os-zhuang

观察

#5352 / #5367 处理的是 rest-server.ts 里那串「按 message 措辞决定 HTTP 码」的正则。packages/services/service-analytics/src/analytics-service.ts 里还有第二个同类嗅探器,而且它的后果比选错状态码更重:命中即把错误换成一个空结果。

// analytics-service.ts:83
function isMissingSourceError(err: unknown): boolean {
  const msg = String((err as { message?: unknown })?.message ?? err ?? '').toLowerCase();
  return (
    msg.includes('no such table') ||
    (msg.includes('relation') && msg.includes('does not exist')) ||
    msg.includes("doesn't exist") ||
    msg.includes('not registered') ||
    msg.includes('unknown object') ||
    msg.includes('is not a registered object')
  );
}

命中后 queryDataset 的 catch(analytics-service.ts:700)会 logger.warn 一句然后
return { rows: [], fields: [], totals: [] } —— 也就是 widget 画一个自信的空图,而不是报错。
这个降级本身是刻意的(对象没在本 kernel 挂载时 widget 应当显示「无数据」而非 500),#5033 已经把跨库那一支拆出来单独响亮报错。问题在于判据是措辞。

已经存在的一次命中(今天无害)

dataset-compiler.ts:260 的拒收原文:

[dataset-compiler] dataset "X" includes relationship "R" which does not exist on object "O".

它同时含 relation(在 relationship 里)和 does not exist → isMissingSourceError 返回 true。

今天不出事的唯一原因是抛点在 try 之外:queryDataset 先 const compiled = this.registerDataset(dataset)(第 626 行,compileDataset 在这里抛),而那个 try/catch 在第 697 行才开始。也就是说这是一条已经装好但没接电的雷:

属于 observation 类:今天没有用户会撞到,grep 也不会告诉你两条措辞正在互相纠缠。

可能的方向(不预判,留给 triage)

  • A. 判据换成结构而非措辞:让「源缺失」由驱动侧带 code(例如 ERR_DATASOURCE_UNAVAILABLE 已在 ERROR_CODE_LEDGER 里)或由 isRegisteredObject 探针回答,isMissingSourceError 退化为兼容层并排到 code 判据之后。
  • B. 最小防守:降级路径只对「不带 ADR-0112 信封的错误」生效 —— 一个已经自称 4xx 的拒收(analytics dataset 路由的 message 正则兜底没有退休时间表:六族拒收仍靠措辞分类,改一个字就换一个 HTTP 码 #5367 之后 dataset-compiler 的两处就是)永远不该被降级成空结果。这一条无论 A 做不做都成立,且能直接把上面那条雷拆掉。
  • C. 收紧 relation/does not exist 这一支,让它只匹配 Postgres 的实际措辞(relation "x" does not exist,带引号的关系名),而不是任意同时含两个词的句子。

参考

Activity

  1. added
    domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 6, 2026
  2. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    ContributorAuthor

    发现分诊(#4949 纪律):晋级,摘 finding 换 pm:queue,domain:services 已在(落点 packages/services/service-analytics/src/analytics-service.ts)。

    一行理由:已核 origin/main —— 嗅探器(:83)与命中措辞(dataset-compiler.ts:262)均仍在,「装好没接电的雷」成立;方向 B(带 ADR-0112 信封自称 4xx 的拒收永不降级成空结果)是自包含、无论 A 做不做都成立的最小拆雷,#5352/#5367 同反模式清理先例在前 —— 值得现在拆,不值得等踩响。范围限 B(+C 可选收紧措辞支);方向 A(驱动侧结构化 code)涉 drivers 面,需要时独立立单。与 #5669(analytics where 无闸门)、#5353 同包在飞/在队,认领方注意同包串行。

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. hotlong commented on Aug 6, 2026

    @hotlong
    Contributor

    重定价注记(services 座位,#5716 验收后 —— 派发本单前以此为准,⛔ 不沿用立单时的成本模型):


    Generated by Claude Code

  4. self-assigned this
    on Aug 6, 2026
  5. hotlong commented on Aug 6, 2026

    @hotlong
    Contributor

    认领:PM 循环第 4 轮(services 车道)
    会话:session_015a5qkLzpGXhLL2F5gvJ7dD
    分支:claude/issue-5717-no-degrade-enveloped-errors
    Worktree:objectstack-issue-5717
    域:domain:services
    文件面:packages/services/service-analytics/src/analytics-service.ts(isMissingSourceError 降级路径,现 :92/:796)+ 同包测试;⛔ 不触 buildQuery/粒度判据(#6003 刚合面)、不触各拒收 throw 本体(#5963 面)、不触 drivers(方向 A 出界,分诊已限定)
    串行约束已清:#6003 今日刚合(同文件,行号已移),基于合并后 origin/main;同包无其它在飞(#6007 待分诊,不同函数)

    执行口径:分诊晋级评论限定范围 B(+C 可选);重定价注记(13:19Z)在案 —— #5963 之后 compiler 站点已带信封,B 从今天起覆盖它。派发令随后。


    Generated by Claude Code

  6. hotlong commented on Aug 6, 2026

    @hotlong
    Contributor

    验收:ACCEPT → PR #6045(实质检查全绿;两个被平台故障 cancel 的 Dogfood job 已重排,绿后转 ready 入队,本座位跟到 MERGED)。

    经办:services 座位,会话 session_015a5qkLzpGXhLL2F5gvJ7dD(第 4 轮)。


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landedpm:dispatchedDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loop

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions