Skip to content

Cloudflare Workflow instrumentation leaves pending waitUntil tasks after the flush timeout #24482

Description

@matthewbjones

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/cloudflare

SDK Version

10.71.0

Framework Version

Cloudflare Workers Workflows; Wrangler 4.126.0

Link to Sentry event

No response

Reproduction Example/SDK Setup

import * as Sentry from "@sentry/cloudflare";
import { WorkflowEntrypoint } from "cloudflare:workers";

class ReproductionWorkflow extends WorkflowEntrypoint {
  async run(_event, step) {
    for (let index = 0; index < 100; index++) {
      await step.do(`step-${index}`, async () => index);
    }
  }
}

export const ReproductionWorkflowWithSentry = Sentry.instrumentWorkflowWithSentry(
  () => ({
    // This test endpoint accepts Sentry envelopes but delays its response
    // for 120 seconds.
    dsn: "https://public@<delayed-endpoint>/1",
    tracesSampleRate: 1,
    enableLogs: false,
    sendClientReports: false,
  }),
  ReproductionWorkflow,
);

Steps to Reproduce

  1. Deploy an HTTP endpoint that accepts requests and delays every response for 120 seconds.
  2. Configure the instrumented Workflow’s DSN to use that endpoint.
  3. Deploy and trigger the Workflow with 100 trivial step.do() calls.
  4. In Cloudflare Observability, search the Worker’s events for "tasks did not complete".

Expected Result

Sentry’s flush(2000) timeout should settle all Sentry-owned waitUntil work within two seconds, including cancelling any pending transport request. No waitUntil cancellation warning should be emitted.

Actual Result

Cloudflare emits:

"waitUntil() tasks did not complete within the allowed time after invocation end and have been cancelled."

The Workflow itself completes successfully, but Sentry-owned work remains pending after the flush timeout.

Additional Context

Investigation identified three places where the configured flush timeout was not fully enforced:

  1. The transport drain returned false after its timeout but did not abort the pending fetch request.
  2. Workflow steps reused flushPointReached from the previous step, causing later steps to register unnecessary eager waitUntil flushes.
  3. CloudflareClient.flush() awaited flushLock.finalize() outside the configured timeout.

We reproduced the warning in a deployed Cloudflare Workflow using a transport endpoint that delayed every response for 120 seconds. After addressing all three paths, 20/20 Workflow instances completed with zero matching warnings in Cloudflare Observability.

Each defect has a red/green regression test. The complete @sentry/cloudflare test suite passes (955/955), along with lint, build, and typecheck.

Priority

No response

Activity

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