Skip to content

feat(core): Deprecate op and forceTransaction options in StartSpanOptions - #23819

Closed
Lms24 wants to merge 4 commits into
developfrom
feat/deprecate-force-transaction-and-op
Closed

Lms24 wants to merge 4 commits into
developfrom
feat/deprecate-force-transaction-and-op

Conversation

@Lms24

@Lms24 Lms24 commented Sep 1, 2026

Copy link
Copy Markdown
Member

This PR:

  • deprecates the forceTransaction StartSpanOptions property
    • the replacement is to
      • no longer use it if the span was promoted to a transaction for indexing/searchabilitiy reasons
      • or wrap it with Sentry.continueTrace(Sentry.withActiveSpan(null, Sentry.startSpan())). Not a pretty workaround but based on feedback and needs, we can evaluate adding a helper or a new forceSegment (naming TBD) option
    • added lint disable comments for our remaining use cases
  • deprecates the forceTransaction StartSpanOptions property
    • replacement is the sentry.op attribute which is straight forward
    • all remaining op usages were replaced
    • beforeSendSpan callback adjusted to backfill top-level op from sentry.op attribute

Lms24 and others added 3 commits September 1, 2026 09:40
`forceTransaction` no longer has a concrete use case: all spans are indexed and searchable in Sentry,
so a span does not need to be a transaction to be queried, filtered or aggregated on. The option will
be removed in the next major version.

For the remaining cases where a span genuinely has to be a segment (root) span, the JSDoc points to
starting it without a parent span (`withActiveSpan(null, ...)`, optionally inside `continueTrace`)
instead of forcing it into a transaction.

Internal SDK usages are suppressed with an oxlint directive for now and will be evaluated separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`op` duplicates the `sentry.op` span attribute, which is the canonical way to categorize a span. It
will be removed in a future version; the deprecation deliberately does not name a specific one.

All internal usages are rewritten to set `sentry.op` (via the `SENTRY_OP` constant from
`@sentry/conventions`) instead. Precedence is unchanged everywhere: an explicit `sentry.op` attribute
still wins over `op`. Call sites that already set both now only set the attribute.

`browserTracingIntegration` is the one exception that still touches `op`: `beforeStartSpan` is a
public hook that receives and may override it, so the option is kept in the options handed to the
hook and only folded into `sentry.op` afterwards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Lms24
Lms24 requested review from a team as code owners September 1, 2026 09:47
@Lms24
Lms24 requested review from isaacs, msonnb, mydea and nicohrubec and removed request for a team September 1, 2026 09:47
@Lms24
Lms24 marked this pull request as draft September 1, 2026 09:47
Comment on lines +354 to +358
// oxlint-disable-next-line typescript/no-deprecated
if (finalStartSpanOptions.op !== originalOp) {
// oxlint-disable-next-line typescript/no-deprecated
attributes[SENTRY_OP] = finalStartSpanOptions.op;
}

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: If a beforeStartSpan callback returns an options object without the op field, the span's operation (SENTRY_OP) attribute is incorrectly deleted, breaking UI categorization.
Severity: HIGH

Suggested Fix

Modify the condition to ensure finalStartSpanOptions.op is defined before comparing it to originalOp. For example: if (finalStartSpanOptions.op !== undefined && finalStartSpanOptions.op !== originalOp).

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/browser/src/tracing/browserTracingIntegration.ts#L354-L358

Potential issue: When a `beforeStartSpan` callback returns a new options object that
omits the deprecated `op` field, the check `finalStartSpanOptions.op !== originalOp`
incorrectly evaluates to `true` because `finalStartSpanOptions.op` is `undefined`. This
leads to `attributes[SENTRY_OP]` being set to `undefined`. Subsequently, when
`SentrySpan.setAttribute` is called with an `undefined` value, it deletes the
`SENTRY_OP` key from the span's attributes. This causes pageload and navigation spans to
lose their operation type, which breaks filtering and categorization in the Sentry UI.
This is triggered by a common usage pattern recommended in documentation.

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

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 2 potential issues.

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 2fa39b2. Configure here.

Comment thread packages/browser/src/tracing/browserTracingIntegration.ts
* }),
* ),
* );
* ```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Feat PR lacks integration tests

Low Severity

Flagged because the review rules require feat PRs to include at least one integration or E2E test. This change deprecates op and forceTransaction and migrates route span creation to sentry.op, but the diff only updates existing unit tests.

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

Reviewed by Cursor Bugbot for commit 2fa39b2. Configure here.

@Lms24

Lms24 commented Sep 1, 2026

Copy link
Copy Markdown
Member Author

superseded by #23821 and #23822

@Lms24 Lms24 closed this Sep 1, 2026
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