Problem
Investigation under BS#1271 surfaced two observability gaps that are independent of the root-cause controller fix:
Gap 1 — setupExpressErrorHandler didn't capture a bare TypeError
The POST /flowsheet burst captured under BS#1271 produced 8 spans with http.response.status_code: 500 and span.status: internal_error, but zero matching captured exceptions in the Sentry errors dataset. The errorHandler is wired correctly:
apps/backend/app.ts:150 — Sentry.setupExpressErrorHandler(app, { shouldHandleError: shouldCaptureExpressError })
apps/backend/app.ts:151 — app.use(errorHandler) (centralized handler that emits a 500 for non-WxycError)
apps/backend/middleware/sentryErrorFilter.ts — shouldCaptureExpressError returns true for any non-LmlClientError with missing / NaN / ≥500 statusCode
A bare TypeError has no statusCode, so the filter resolves to true. The SDK should have captured. It didn't.
The "Mirror: create_entry failed" capture on POST /flowsheet (backend@v0.1.507, 2026-06-08) shows Sentry.captureException works in this transaction — so the gap is specific to setupExpressErrorHandler's express-middleware path, not Sentry's transport.
SDK: @sentry/node ^10.53.1.
Gap 2 — user.* attributes empty on http.server spans
All 8 failing http.server spans return empty for user.id, user.username, user.email, user.ip even though every failing request carried a JWT and went through requirePermissions. The user/ DJ attribution that would have let us identify the affected DJ's session is missing.
Why this matters
Together these gaps mean: when a 5xx code path doesn't have an explicit Sentry.captureException, the failure mode shows up as a span-only signal with no user attribution and no exception detail. Diagnosing BS#1271 required reading raw spans + correlating against existing tests; with the SDK working as documented, the bare TypeError would have surfaced as a typed Sentry issue immediately.
Next steps (suggested)
- Reproduce
setupExpressErrorHandler skipping a bare TypeError on Express 5 async-handler with @sentry/node ^10.53.1. The shouldHandleError option name may be silently deprecated in v10; check the SDK changelog / source.
- If the SDK no longer honors
shouldHandleError: either re-implement the LmlClientError filter as beforeSend, or stop relying on auto-capture and add explicit Sentry.captureException at controller boundaries that do 5xx.
- Investigate why http.server spans don't carry
user.* attributes. Probably needs an httpIntegration({ requestHook }) to read req.auth?.id and tag the span / scope.
Out of scope
Problem
Investigation under BS#1271 surfaced two observability gaps that are independent of the root-cause controller fix:
Gap 1 —
setupExpressErrorHandlerdidn't capture a bare TypeErrorThe POST /flowsheet burst captured under BS#1271 produced 8 spans with
http.response.status_code: 500andspan.status: internal_error, but zero matching captured exceptions in the Sentry errors dataset. The errorHandler is wired correctly:apps/backend/app.ts:150—Sentry.setupExpressErrorHandler(app, { shouldHandleError: shouldCaptureExpressError })apps/backend/app.ts:151—app.use(errorHandler)(centralized handler that emits a 500 for non-WxycError)apps/backend/middleware/sentryErrorFilter.ts—shouldCaptureExpressErrorreturnstruefor any non-LmlClientError with missing / NaN /≥500statusCodeA bare TypeError has no
statusCode, so the filter resolves totrue. The SDK should have captured. It didn't.The "Mirror: create_entry failed" capture on POST /flowsheet (
backend@v0.1.507, 2026-06-08) showsSentry.captureExceptionworks in this transaction — so the gap is specific tosetupExpressErrorHandler's express-middleware path, not Sentry's transport.SDK:
@sentry/node ^10.53.1.Gap 2 —
user.*attributes empty on http.server spansAll 8 failing http.server spans return empty for
user.id,user.username,user.email,user.ipeven though every failing request carried a JWT and went throughrequirePermissions. The user/ DJ attribution that would have let us identify the affected DJ's session is missing.Why this matters
Together these gaps mean: when a 5xx code path doesn't have an explicit
Sentry.captureException, the failure mode shows up as a span-only signal with no user attribution and no exception detail. Diagnosing BS#1271 required reading raw spans + correlating against existing tests; with the SDK working as documented, the bare TypeError would have surfaced as a typed Sentry issue immediately.Next steps (suggested)
setupExpressErrorHandlerskipping a bare TypeError on Express 5 async-handler with@sentry/node ^10.53.1. TheshouldHandleErroroption name may be silently deprecated in v10; check the SDK changelog / source.shouldHandleError: either re-implement the LmlClientError filter asbeforeSend, or stop relying on auto-capture and add explicitSentry.captureExceptionat controller boundaries that do 5xx.user.*attributes. Probably needs anhttpIntegration({ requestHook })to readreq.auth?.idand tag the span / scope.Out of scope