sentry-javascript icon indicating copy to clipboard operation
sentry-javascript copied to clipboard

Sentry does not capture errors or spans from Cloudflare Workers context.waitUntil()

Open the-leonat opened this issue 3 months ago • 5 comments

Is there an existing issue for this?

  • [x] I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
  • [x] I have reviewed the documentation https://docs.sentry.io/
  • [x] I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/cloudflare - hono

SDK Version

10.7.0

Framework Version

Hono 4.9.4

Link to Sentry event

No response

Reproduction Example/SDK Setup

export default Sentry.withSentry(
    (_env) => {
        const env = checkBindings(_env)
        const sentryEnabledEnvs: (typeof env.WORKER_ENVIRONMENT)[] = ["production", "staging"]
        const enabled = sentryEnabledEnvs.includes(env.WORKER_ENVIRONMENT)
        if (!enabled) console.info(`Sentry is disabled in env "${env.WORKER_ENVIRONMENT}"`)
        const tracesSampleRate = env.WORKER_ENVIRONMENT === "production" ? 0.1 : 1

        return {
            dsn: env.SENTRY_DSN,
            release: env.VERSION_ID,
            sendDefaultPii: true,
            environment: env.WORKER_ENVIRONMENT,
            enableLogs: true,
            tracesSampleRate,
            enabled,
            integrations: [
                Sentry.consoleLoggingIntegration({ levels: ["log", "error", "warn"] }),
            ],
        }
    },
    app,
)

Steps to Reproduce


import { waitUntil } from "cloudflare:workers"


 .get("/route", async (context) => {
        // some business logic

        async function updateDBAndCache() {
            return Sentry.startSpan({ name: "Update DB and Cache" }, async () => {
                const data = await updateDB()
                await context.get("setMember")(data)
            })
        }
        waitUntil(updateDBAndCache())
        return context.json(result, 200)
    })

 .get("/route-with-error", async (context) => {
        // some business logic

        async function updateDBAndCache() {
            return Sentry.startSpan({ name: "Update DB and Cache" }, async () => {
                const data = await updateDB()
                throw new Error("expected error")
                await context.get("setMember")(data)
            })
        }
        waitUntil(updateDBAndCache())
        return context.json(result, 200)
    })

Expected Result

Span "Update DB and Cache" appears in Sentry as well as seeing the captured exception.

Actual Result

All spans and exceptions in waitUntil are lost.

the-leonat avatar Aug 28 '25 14:08 the-leonat

Hey @the-leonat thanks for reaching out. As per docs I think you should rather use tail workers for this use case instead.

chargome avatar Aug 29 '25 12:08 chargome

Hey @the-leonat thanks for reaching out. As per docs I think you should rather use tail workers for this use case instead.

I understand how to capture errors with tailworkers, but I’m looking for a way to instrument fetch calls and add tracing for calls inside .waitUntil. From my understanding, tailworkers aren’t meant to run business logic, so persistence and cache updates should remain in the main worker. I briefly looked at the sentry/cloudflare source and noticed PR #16681, which seems related to my initial issue. Could you confirm whether sentry/cloudflare intends to support capturing spans and exceptions within .waitUntil, or if that isn’t currently supported?

the-leonat avatar Aug 29 '25 13:08 the-leonat

Hi @the-leonat, we'll explore if it's feasible for us to capture spans and exceptions within waitUntil.

andreiborza avatar Sep 01 '25 11:09 andreiborza

To give a short update here. I think it would make sense to make this work. In general this is not Hono specific - so this should work for all use cases. I will investigate on what is needed

(related #18334)

JPeer264 avatar Nov 26 '25 12:11 JPeer264