Skip to content

fix(cloudflare): Fix instrumentDurableObjectWithSentry breaking Cloudflare Agents#21101

Draft
JPeer264 wants to merge 1 commit into
developfrom
jp/cloudflare-agents-callable-fix
Draft

fix(cloudflare): Fix instrumentDurableObjectWithSentry breaking Cloudflare Agents#21101
JPeer264 wants to merge 1 commit into
developfrom
jp/cloudflare-agents-callable-fix

Conversation

@JPeer264
Copy link
Copy Markdown
Member

By investigating #20099 it seemed that Cloudflare Agents were not working when enableRpcTracePropagation: true was set. The main reason for that was that the original target was not bound to the call.

By doing that I changed the logic a little to also make it more resistant. As the rpc trace was always everywhere attached, even though it could be that it was not directly a real RPC call. No the rpc trace is only attached when in the arguments the __sentry_rpc_meta__ is there as last parameter - which gives an extra layer of safety.

Also BUILT_IN_DO_METHODS is not needed and got removed, as we actually ignore these with the other checks (test was added for it)

The deprecated instrumentPrototypeMethods is still using the previous behavior.

This PR also proofs that we can instrument Agents on Cloudflare (cloudflare-agent e2e test)


AI text on top:

The fix binds ALL methods to the original object, ensuring private fields
work correctly. Additionally, spans are now only created when Sentry RPC
metadata (__sentry_rpc_meta__) is present in the arguments, which is only
the case for actual RPC calls that have trace propagation enabled on the
calling side. This prevents creating spans for internal framework method
calls like those made by the Agents SDK over WebSocket.

…flare Agents

The fix binds ALL methods to the original object, ensuring private fields
work correctly. Additionally, spans are now only created when Sentry RPC
metadata (`__sentry_rpc_meta__`) is present in the arguments, which is only
the case for actual RPC calls that have trace propagation enabled on the
calling side. This prevents creating spans for internal framework method
calls like those made by the Agents SDK over WebSocket.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@JPeer264 JPeer264 requested a review from a team as a code owner May 21, 2026 14:35
@JPeer264 JPeer264 requested review from andreiborza and mydea and removed request for a team May 21, 2026 14:35
TestDurableObjectBase,
);

export default {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: This is needed, as without it we now don't generate rpc traces. So this was fixed as well

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7234674. Configure here.

const rpcMethodCache = new Map<string, UncheckedMethod>();
// When using the deprecated `instrumentPrototypeMethods` option, always create spans.
// When using the new `enableRpcTracePropagation`, only create spans when RPC metadata is present.
const alwaysTrace = options.instrumentPrototypeMethods !== undefined;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alwaysTrace ignores enableRpcTracePropagation

High Severity

alwaysTrace is true whenever instrumentPrototypeMethods is present in options, including false. With enableRpcTracePropagation enabled, RPC prototype methods return the always-traced wrapper instead of the metadata-gated one, so internal calls without __sentry_rpc_meta__ still create RPC spans—reintroducing the Agents regression this PR fixes.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7234674. Configure here.

const rpcMethodCache = new Map<string, UncheckedMethod>();
// When using the deprecated `instrumentPrototypeMethods` option, always create spans.
// When using the new `enableRpcTracePropagation`, only create spans when RPC metadata is present.
const alwaysTrace = options.instrumentPrototypeMethods !== undefined;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The alwaysTrace flag is incorrectly determined by the presence of the deprecated instrumentPrototypeMethods option, ignoring the new enableRpcTracePropagation option and leading to incorrect tracing behavior.
Severity: HIGH

Suggested Fix

The logic for setting the alwaysTrace flag in durableobject.ts should be updated to be consistent with the logic in getEffectiveRpcPropagation. It should prioritize the enableRpcTracePropagation option and correctly handle cases where both the new and deprecated options are present.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/cloudflare/src/durableobject.ts#L136

Potential issue: The logic for determining whether to always create spans for RPC
methods is flawed. The `alwaysTrace` flag is set to `true` if the deprecated
`instrumentPrototypeMethods` option is defined, regardless of its value (`true` or
`false`) and without considering the new `enableRpcTracePropagation` option. This leads
to incorrect behavior in two scenarios. First, if a user sets both
`enableRpcTracePropagation: true` and `instrumentPrototypeMethods: true` during
migration, tracing will be unconditionally enabled, bypassing the intended fix. Second,
if a user sets `instrumentPrototypeMethods: false` to disable it, tracing is still
unconditionally enabled for all methods, which is the opposite of the intended effect.

Did we get this right? 👍 / 👎 to inform future reviews.

@github-actions
Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 27.32 kB - -
@sentry/browser - with treeshaking flags 25.74 kB - -
@sentry/browser (incl. Tracing) 45.31 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 47.55 kB - -
@sentry/browser (incl. Tracing, Profiling) 50.3 kB - -
@sentry/browser (incl. Tracing, Replay) 84.92 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 74.43 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 89.64 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 102.24 kB - -
@sentry/browser (incl. Feedback) 44.51 kB - -
@sentry/browser (incl. sendFeedback) 32.13 kB - -
@sentry/browser (incl. FeedbackAsync) 37.25 kB - -
@sentry/browser (incl. Metrics) 28.41 kB - -
@sentry/browser (incl. Logs) 28.64 kB - -
@sentry/browser (incl. Metrics & Logs) 29.33 kB - -
@sentry/react 29.05 kB - -
@sentry/react (incl. Tracing) 47.55 kB - -
@sentry/vue 32.24 kB - -
@sentry/vue (incl. Tracing) 47.17 kB - -
@sentry/svelte 27.35 kB - -
CDN Bundle 29.73 kB - -
CDN Bundle (incl. Tracing) 47.84 kB - -
CDN Bundle (incl. Logs, Metrics) 31.21 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 49.09 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 70.53 kB - -
CDN Bundle (incl. Tracing, Replay) 85.34 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 86.5 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 91.2 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 92.37 kB - -
CDN Bundle - uncompressed 87.8 kB - -
CDN Bundle (incl. Tracing) - uncompressed 144.29 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 92.29 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 148.05 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 217.02 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 263.07 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 266.81 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 276.77 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 280.5 kB - -
@sentry/nextjs (client) 50.03 kB - -
@sentry/sveltekit (client) 45.8 kB - -
@sentry/core/server 76.41 kB - -
@sentry/core/browser 63.16 kB - -
@sentry/node-core 62.59 kB - -
@sentry/node 162.67 kB -0.84% -1.37 kB 🔽
@sentry/node - without tracing 75.02 kB +0.01% +1 B 🔺
@sentry/aws-serverless 87.24 kB - -
@sentry/cloudflare (withSentry) - minified 173.19 kB +0.04% +63 B 🔺
@sentry/cloudflare (withSentry) 432.58 kB +0.04% +154 B 🔺

View base workflow run

@JPeer264 JPeer264 marked this pull request as draft May 22, 2026 06:23
@JPeer264 JPeer264 removed request for andreiborza and mydea May 22, 2026 06:23
@JPeer264
Copy link
Copy Markdown
Member Author

Some e2e tests are not passing, moving back to draft

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant