Buffered replay can leave an orphaned replay_id link on a replaysOnErrorSampleRate miss
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Accessibilité débutants
- 35/100
- Type d'issue
- Bug
- Clarté
- Plutôt claire
- Activité
- Active
- Stack technique
- android, ios, react-native, typescript
- Domaine
- mobile-dev
Piste de recherche
Commencez par packages/core/src/js/replay/mobilereplay.ts, en particulier tagEventWithReplayId et flushReplayForSentEvent, puis suivez le pipeline beforeSend-to-afterSendEvent décrit dans l’issue. Reproduisez le problème avec buffered/on-error mobile replay, replaysOnErrorSampleRate inférieur à 1 et error sampleRate à 1.0. Le travail est terminé lorsque l’événement n’est associé à un replay que si le SDK natif téléversera ce replay, sans provoquer de régression de #6598.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Background
PR #6685 fixed #6598 (a buffered/on-error replay was uploaded for an error later dropped by error sampleRate, orphaning the replay). Since @sentry/core 10.70.0 (getsentry/sentry-javascript#22819) the error sampleRate roll runs after beforeSend, so the fix splits the work:
tagEventWithReplayId(in thebeforeSendwrapper) links the event to the buffered replay id — no flush.flushReplayForSentEvent(inafterSendEvent, which only fires for events that survive sampling) performs the native flush viaNATIVE.captureReplay().
This fully fixes the reported case. This issue tracks a narrower residual gap that the split introduces.
The gap
The buffered replay id we tag with in beforeSend is provisional: native assigns it when recording starts, but whether the buffer is actually uploaded depends on the replaysOnErrorSampleRate roll, which happens later inside the async captureReplay() flush.
When an error survives error sampleRate but the replaysOnErrorSampleRate roll misses, the event has already been serialized and sent carrying contexts.replay.replay_id, while no replay is ever uploaded → the event links to a replay that doesn't exist.
Only occurs when replaysOnErrorSampleRate is set below 1.0. Impact is limited to a dangling link (the event's Replay tab resolves to nothing); no replay data or quota is wasted.
Steps to reproduce
- Configure mobile replay in buffer/on-error mode with
replaysOnErrorSampleRatebetween 0 and 1 (e.g.0.5) and errorsampleRate: 1.0. - Trigger errors until one hits the
replaysOnErrorSampleRatemiss branch. - Observe the error event in Sentry carries a
replay_idbut the referenced replay was never uploaded.
Why it isn't fixable in the JS layer alone
The pipeline order is fixed by @sentry/core:
beforeSend → [error sampleRate gate] → serialize + send → afterSendEvent
(tag here) (flush here)
- Tagging must happen before send (the link must be in the outgoing event).
- Flushing must happen after the sampleRate gate (flushing earlier reintroduces #6598).
- So the flush — and the
replaysOnErrorSampleRateroll inside it — can only run inafterSendEvent, after the event is already sent. Thereplay_idis gone over the wire and can't be conditionally removed. - The only hook between the gate and transmission is
beforeEnvelope, butcaptureReplay()is an async bridge call and can't block the send. A synchronous native flush isn't viable (it does I/O; the old-arch bridge has no sync methods).
Proposed fix (native)
Provide a way for the native SDKs (sentry-cocoa / sentry-android) to decouple the on-error sampling decision from the buffer upload, so RN can reconcile tag and upload. Either:
- (a) expose the
replaysOnErrorSampleRatedecision as a synchronous, side-effect-free query the RN layer can call inbeforeSend(tag only when it will capture), the decision being cached so the later flush honors the same result; or - (b) decouple the decision from the upload so the tag and the eventual upload always agree.
Relationship to #6598
This is the opposite orphaning direction from #6598, and gated by a different sample rate:
| #6598 (fixed) | #6696 (this issue) | |
|---|---|---|
| Orphan direction | replay with no event | event with no replay |
| Caused by | the bug (flush before sampling) | the fix's optimistic tagging |
| Gate | sampleRate < 1 |
replaysOnErrorSampleRate < 1 |
| Severity | quota waste + orphaned replay | harmless dangling link |
| Scope | broad (any dropped error) | narrow (survives sampleRate and replay roll misses) |
The fix in #6685 traded a broad, quota-costing orphaned replay for this rare, harmless orphaned link.
References
- Fix PR: #6685
- Original issue: #6598
- Upstream ordering change: getsentry/sentry-javascript#22819
- Code:
packages/core/src/js/replay/mobilereplay.ts(tagEventWithReplayId,flushReplayForSentEvent)
- Langage dominant
- TypeScript
- Étoiles
- 1.8k
- Forks
- 371
- Merge moyen
- 1 j 6 h
- PR mergées (30 j)
- 114
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de getsentry/sentry-react-native
-
React-Native Replays Task
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
getsentry/sentry-react-native#6680 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Improvement React-Native
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
getsentry/sentry-react-native#6143 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
React-Native Task User Feedbacks
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
getsentry/sentry-react-native#5932 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
React-Native Replays Task
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
getsentry/sentry-react-native#5882 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Good First Issue React-Native Task
Difficulté 1/5 Moins d'une heure Accessibilité débutants 65/100
getsentry/sentry-react-native#5771 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de getsentry/sentry-react-native
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 62/100
oxidecomputer/skepsis#102 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 62/100
voidzero-dev/void#677 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
kunchenguid/gh-axi#247 ·
Les mainteneurs répondent en général sous 1 jour
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
lidge-jun/opencodex#8101 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour