fix(telemetry): sharpen Sentry signal for v2.1.0 residual defects (#498)

Follow-ups to the v2.1.0 Sentry telemetry overhaul, found by reviewing live release:2.1.0 events:

- error_code tag was empty because reportError read only the top-level err.code; add extractErrorCode() to walk the cause chain (pg SQLSTATE, node E-code, else first short code).
- InputValidationError from a tool's processV2 in the worker was logged as error_class=bug; classify it as expected for any source. Worker-side ZodError stays a bug (schema drift).
- AI dispatcher timeouts rejected with a bare Error, which the sanitizer scrubbed to a message-less "Error: Error"; reject with an operational SafeError (code "timeout") at both timeout sites.

Each fix written failing-test-first; affected and adjacent unit suites green plus full CI (integration + e2e).
This commit is contained in:
SnapOtter
2026-07-11 16:18:26 +08:00
committed by GitHub
parent b8c3700c15
commit b457596649
7 changed files with 165 additions and 7 deletions
@@ -102,6 +102,30 @@ export function rebuildErrorValue(err: unknown): string | null {
}
}
/**
* The most specific, non-sensitive error code in the cause chain, for the
* Sentry `error_code` tag. Prefers a pg SQLSTATE, then a node E-code, else the
* first short string code found (e.g. a SafeError's authored code). Returns
* null when none is present. reportError used to read only the top-level
* `.code`, but pg/undici bury the real code under a drizzle/wrapper Error whose
* own `.code` is undefined, so the tag was always empty on those events.
*/
export function extractErrorCode(err: unknown): string | null {
try {
let fallback: string | null = null;
for (const l of chain(err)) {
const code = l.code;
if (typeof code !== "string" || code.length === 0 || code.length > 40) continue;
if (SQLSTATE.test(code) && !NODE_CODE.test(code)) return code;
if (NODE_CODE.test(code)) return code;
if (fallback === null) fallback = code;
}
return fallback;
} catch {
return null;
}
}
export type ConnectivityClass = "pg-unavailable" | "redis-unavailable" | "net-unavailable";
/** Infra-connectivity classification used for fingerprinting + throttling. */