diff --git a/apps/cloud/src/server.ts b/apps/cloud/src/server.ts index e941de78d..0ac72c93f 100644 --- a/apps/cloud/src/server.ts +++ b/apps/cloud/src/server.ts @@ -22,11 +22,12 @@ const sentryOptions = (env: Env) => ({ enableLogs: true, sendDefaultPii: true, skipOpenTelemetrySetup: true, - // Our DO methods (init/handleRequest/alarm) live on the prototype, not on - // the instance. Sentry's default DO auto-wrap only visits own properties, - // which misses prototype methods — so errors thrown inside init() never - // reach Sentry. This flag opts into prototype-method instrumentation. - instrumentPrototypeMethods: true, + // NOTE: do NOT enable `instrumentPrototypeMethods`. It walks the DO prototype + // and reads every property — including accessors — to find methods to wrap, + // which invokes the `sessionId` getter with `this` bound to the prototype + // (where `ctx` is undefined) and throws during construction, 500ing every + // session create / cold restore. The DO captures its own errors via the + // `captureCause` seam (→ Sentry) instead. }); // --------------------------------------------------------------------------- diff --git a/packages/hosts/cloudflare/src/mcp/session-durable-object.ts b/packages/hosts/cloudflare/src/mcp/session-durable-object.ts index 943368ac6..250911f31 100644 --- a/packages/hosts/cloudflare/src/mcp/session-durable-object.ts +++ b/packages/hosts/cloudflare/src/mcp/session-durable-object.ts @@ -628,6 +628,10 @@ export abstract class McpSessionDOBase< Effect.tapCause((cause) => Effect.gen(function* () { console.error("[mcp-session] init failed:", Cause.pretty(cause)); + // Report to the host's error sink (cloud → Sentry). init() runs on + // the prototype, which Sentry's auto-wrap doesn't cover, so capture + // here explicitly rather than relying on prototype instrumentation. + self.captureCause(cause); // Annotate `McpSessionDO.init` (the active span here — `doInit` opens // none of its own) so the surviving, flushed span names the frame. yield* self.recordCauseOnSpan(cause);