Skip to content

@sentry/cloudflare/vite: Auto-instrumentation skips the Worker when wrangler main is a package specifier #24522

Closed

Description

@JPeer264

Description

sentryCloudflareVitePlugin() does not wrap the Worker when main in the Wrangler config is a package specifier and not a file path. The build succeeds, but the bundle contains no Sentry code, and the plugin logs no warning.

@cloudflare/vite-plugin supports this config, and vinext generates it by default with vinext init --platform=cloudflare:

// wrangler.jsonc
{
  "main": "vinext/server/fetch-handler",
  // ...
}
// vite.config.ts
export default defineConfig({
  plugins: [
    vinext(),
    cloudflare({ viteEnvironment: { name: "rsc", childEnvironments: ["ssr"] } }),
    sentryCloudflareVitePlugin(),
  ],
});

Tested with @sentry/cloudflare@11.0.0-rc.0, @cloudflare/vite-plugin@1.56.0, wrangler@4.135.0, vinext@1.0.0-beta.10 and Vite 8.3.

Cause

resolveWranglerConfig() calls unstable_readConfig() without preserveOriginalMain (wranglerConfig.ts#L70). Wrangler then resolves every main as a path relative to the config file:

main: "vinext/server/fetch-handler"
-> <project>/vinext/server/fetch-handler   (file does not exist)

autoInstrument.ts compares this path with the module IDs in transform (L75), so no module matches. resolveInstrumentFile() also looks for instrument.server.* in the directory of this path (instrumentFile.ts#L23), and a package entry has no such file.

@cloudflare/vite-plugin handles the same value differently:

  1. It reads the config with unstable_readConfig(..., { preserveOriginalMain: true }).
  2. maybeResolveMain() makes main absolute only when it ends with a JS or TS extension.
  3. It resolves the entry with Vite: await this.resolve(workerConfig.main).

Workaround

Add a local entry that re-exports the package entry, and set main to it. Put instrument.server.ts in the same directory:

// worker/index.ts
import handler from "vinext/server/fetch-handler";

export default handler;
{ "main": "./worker/index.ts" }

Proposed fix

  • Read the config with preserveOriginalMain: true, and keep a package specifier unchanged.
  • Resolve main with this.resolve() (for example in buildStart, or lazily in transform), and compare the resolved module ID.
  • When the resolved entry is in node_modules, look for instrument.server.* in the Wrangler config directory (the Vite root) and not next to the entry.
  • Log a warning when main does not resolve to a module that the plugin transforms, so the failure is not silent.
  • Add a test fixture where main is a package specifier.

Activity

  1. linear-code commented on Sep 19, 2026

    @linear-code
  2. ihsraham commented on Sep 27, 2026

    @ihsraham
    Contributor

    I reproduced this with a freshly packed SDK from bd3ce5f, using the repo's pinned Vite 7.3.5, Cloudflare plugin 1.34.0 and Wrangler 4.86.0.

    The same handler captures errors as a file entry or through a local file adapter. As a package export, it builds and serves requests, but the output has no Sentry wrapper and the build gives no Sentry warning. I also checked a Wrangler config below the Vite root.

    Is anyone working on this? I'd like to take the package-entry resolution and a regression test, preserving file-entry behavior. For package entries, should instrument.server.* be read beside the Wrangler config?

  3. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Sep 27, 2026
  4. JPeer264 commented on Sep 28, 2026

    @JPeer264
    MemberAuthor

    Feel free to work on it

    I'd like to take the package-entry resolution and a regression test, preserving file-entry behavior.

    You could also update the following E2E test. The ticket states Vinext, as I tried it there, but it also valid for Astro: https://github.com/getsentry/sentry-javascript/blob/954e9694a2bd983c14e0de3b665568c46c60785f/dev-packages/e2e-tests/test-applications/astro-6-cf-workers/sentry.server.config.js

    Best case scenario is that this file goes away and we only have a instrument.server.* file that uses defineCloudflareOptions (and the wrangler config has "main": "@astrojs/cloudflare/entrypoints/server"). Rest is then automagically done by the Vite plugin.

    For package entries, should instrument.server.* be read beside the Wrangler config?
    Yes, that'd be nice. In the future I think it's good if this can be changed via an option, but no need for now to add this.

  5. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Sep 28, 2026
  6. assigned and unassigned on Oct 14, 2026
  7. isaacs commented on Oct 14, 2026

    @isaacs
    Member

    @ihsraham I'm able to take this on, if you haven't gotten around to it yet. But I thought I'd check in, in case you have a PR that you're hoping to send, don't want to scoop your efforts 😅

    If I don't hear from you, I'll get a PR open for it soon.

  8. ihsraham commented on Oct 14, 2026

    @ihsraham
    Contributor

    @isaacs Thanks for checking in. I haven't been able to finish this, so please go ahead and take it on. I appreciate you offering to help.

  9. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Oct 14, 2026
  10. added a commit that references this issue on Oct 14, 2026
    86fcec8
  11. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Oct 14, 2026
  12. added a commit that references this issue on Oct 14, 2026
    9516aeb
  13. github-actions commented on Oct 15, 2026

    @github-actions
    Contributor

    A PR closing this issue has just been released 🚀

    This issue was referenced by PR #25343, which was included in the 11.8.0 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions