Repository navigation
Conversation
size-limit report 📦Compared: 9da6b7b (PR test merge using develop at 5b78f8e) Against: 5b78f8e (develop) · base run #65360 ✅ Baseline matches: this diff contains only this PR's changes.
|
Optional E2E testsSome optional checks were not successful. They do not block the merge. 6 not successful, 51 successful. See the run.
Successful checks
|
aceecc2 to
398034e
Compare
`@sentry/astro` had no `workerd` export, so a Pages build resolved it to the browser SDK and the server config initialized a `BrowserClient`. A new worker entry backs the server SDK with `@sentry/cloudflare`. Outside a `withSentry` invocation, `CloudflareClient` sends envelopes eagerly without a `waitUntil`, and `flush()` returned before those sends finished, so the runtime cancelled them when the response ended. `flush()` now waits for them.
…` wrap The Worker entry's `withSentry` wrap inits a client from the Wrangler bindings on each request, and the isolate keeps the first client. The user's `sentry.server.config` only loaded later from SSR pages (never for API routes), so their `Sentry.init` got the bindings-only client back and their options were ignored. The entry now imports the server init above the wrap.
The new `workerd` entry re-exports `handleRequest`, whose middleware imported core helpers through `@sentry/node`, pulling the Node SDK into Cloudflare bundles. The bundler entry test now covers `@sentry/astro` under `workerd` and `worker`, with known violations marked per case so only the Node entry stays exempt.
Without a `sentry.server.config`, the integration's default init has no DSN. Running it before the `withSentry` wrap made the isolate keep that client, so the wrap's `SENTRY_DSN` binding was ignored and nothing was sent. The entry now imports the server init only when the user has a config file.
A `Sentry.init` without a `dsn` relied on the `withSentry` wrap filling it from the bindings. Now that the user's init runs first and the isolate keeps that client, it ended up without a DSN. A new `workerd` entry reads the bindings from `cloudflare:workers`, and `init` merges them the same way the wrap does. The generic `worker` condition keeps the entry without that import, since only Cloudflare's bundlers resolve it.
398034e to
0777aa5
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0777aa5. Configure here.
| : [ | ||
| sentryCloudflareNodeWarningPlugin(), | ||
| sentryCloudflareVitePlugin({ importServerInit: !!pathToServerInit }), | ||
| ], |
There was a problem hiding this comment.
Pages wrap can shadow server init
High Severity
The Workers path now passes importServerInit so sentry.server.config runs before withSentry caches a client. The Pages branch still calls sentryCloudflareVitePlugin() without that flag, even though it applies the same wrap. withSentry inits at the start of fetch, so a lazily loaded middleware init can lose to a bindings-only client and drop the user's dsn, tunnel, and environment.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0777aa5. Configure here.


This PR addresses a few issues I found while investigating some comments on #25999
CF Pages runs the browser SDK on the server
This means it will immediately crash if we ship anything that assumes a server-side SDK is being used, this showed up when I tried to use the
serveTunnelIntegrationon the other PR, it doesn't exist on the client SDKs.This happens because we do not have an
exportscondition forworker/workerdlike other SDKs. So@sentry/astroresolves toindex.client.js.We had no E2E apps covering this so it never came up, also it doesn't happen while using
withSentry. But a user trying to callSentry.initfrom@sentry/astrowill trigger the bug.I fixed this by adding a new
workerd/workerexport conditions that point to a newindex.worker.ts, which rexports the cloudflare SDK and uses theinitfrom there.There is a different way to fix it via vite plugins, but I preferred the more "standard" way here.
Cloudflare Client Events are dropped if
withSentryis not usedThis showed up while testing the first issue, the tests were timing out. This is because in CF pages, the
withSentrywrapper is never used so our sends were never registered withwaitUntil, so theflushreturned early, cutting off the requests.I fixed this by making the
flushwait for the previous sends until they are drained. Which also fixes the issue for every possible usage of@sentry/cloudflarethat isn't wrapped bywithSentry.There is no risk of hanging here because each send is already capped by 2 seconds.
The Workers wrapper can shadow the
sentry.server.configclientBecause of the first fix, we now have an order problem. A
withSentrywrapper can override the client that was loaded fromsentry.server.configwhich would break all events, since there is no DSN. The override happens because the wrapper runs first. It's not really an override, more of a "shadowing".This didn't happen before because the first client loaded from the browser bundle and so they never conflicted.
The fix is to ensure the order loads the "correct" init first, which can be arbitrary. I did the following to de-risk the idea:
sentry.server.configfile exists, then it is never added at the top of the import order. So the wrapper client is the only source.sentry.server.configfile exists along with a wrapper client, prefer the server file client.initreads the bindings fromcloudflare:workersand fills unset options the same way the wrap does, so an init without adsnstill picks upSENTRY_DSN. This only lives in theworkerdentry sincecloudflare:workersdoesn't resolve elsewhere.I did think about applying (3) to the cloudflare SDK in general but that may break apps that run it under Node, so need to figure it out later.