HTTP path: TanStack Start + our Effect error handlers swallow throws and return 500 responses, so `Sentry.withSentry` (which only sees uncaught exceptions) never captures them. Adds explicit `Sentry.captureException` in the places that turn errors into 500s: - `toErrorServerResponse` / `toErrorResponse` for the Effect API paths - `handleMcpRequest_POST`'s catch for the MCP proxy path DO path: wraps McpSessionDO with `Sentry.instrumentDurableObjectWithSentry`. Unlike otel-cf-workers' `instrumentDO` (which broke `this` binding on WorkerTransport's stream primitives), Sentry's wrapper uses `Reflect.apply` and is safe. Sets `instrumentPrototypeMethods: true` because the DO's `init` / `handleRequest` live on the prototype — the default auto-wrap only visits own properties, which misses them, and errors thrown inside `init()` never reach Sentry without this flag. Verified end-to-end: debug smoke tests captured both an explicit `captureException` call (HTTP path) and a DO init() throw, both landing in Sentry issues on the node-cloudflare-workers project. Debug endpoints removed before merge.
Showing the changes to apps/cloud/src/api (1 of 3 files). Show all
Unified · Split
| @@ -1,3 +1,4 @@ | ||
| 1 | +import * as Sentry from "@sentry/cloudflare"; | |
| 1 | 2 | import { Data } from "effect"; |
| 2 | 3 | import { HttpServerResponse } from "@effect/platform"; |
| 3 | 4 | |
| @@ -20,12 +21,16 @@ export const isServerError = (error: unknown): boolean => toHttpResponseError(er · 16 unmodified lines | ||
| 20 | 21 | |
| 21 | 22 | export const toErrorResponse = (error: unknown): Response => { |
| 22 | 23 | const mapped = toHttpResponseError(error); |
| 24 | + if (mapped.status >= 500) Sentry.captureException(error); | |
| 23 | 25 | return Response.json({ error: mapped.message, code: mapped.code }, { status: mapped.status }); |
| 24 | 26 | }; |
| 25 | 27 | |
| 26 | 28 | export const toErrorServerResponse = (error: unknown): HttpServerResponse.HttpServerResponse => { |
| 27 | − console.error("[api] toErrorServerResponse error:", error instanceof Error ? error.stack : error); | |
| 28 | 29 | const mapped = toHttpResponseError(error); |
| 30 | + if (mapped.status >= 500) { | |
| 31 | + console.error("[api] toErrorServerResponse error:", error instanceof Error ? error.stack : error); | |
| 32 | + Sentry.captureException(error); | |
| 33 | + } | |
| 29 | 34 | return HttpServerResponse.unsafeJson( |
| 30 | 35 | { error: mapped.message, code: mapped.code }, |
| 31 | 36 | { status: mapped.status }, |