Repository navigation
Conversation
OutboxSender captured the event or transaction through the SDK and then sent each attachment in its own envelope, so filtering or sampling out the parent left orphaned attachments. Collect the attachments of a single-parent envelope up front and pass them on the capture hint, so the client sends them in the same envelope and drops them with the parent. Fixes getsentry#6067
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9097b0b. Configure here.
| } finally { | ||
| if (!attachments.isEmpty()) { | ||
| hint.replaceAttachments(originalAttachments); | ||
| } |
There was a problem hiding this comment.
Rate limits can orphan grouped attachments
Medium Severity
Grouped outbox attachments are added onto the parent and sent as one envelope, but RateLimiter.filter drops items by category. An error or transaction 429 with attachments still allowed strips the parent and forwards the rest, so minidumps can be ingested without their event. Previously a failed parent capture stopped later items, so those attachments never went out alone.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 9097b0b. Configure here.
There was a problem hiding this comment.
I looked at this and I don't think it's a regression. On main, every outbox attachment already goes out in its own envelope through captureEnvelope, so an error or transaction 429 drops the event and the attachments still go out alone. That orphaning exists today, and the PR doesn't add it.
With this change the attachments ride on the parent's hint, so the envelope is built the same way SentryClient builds it for a normal captureEvent with attachments, and RateLimiter.filter treats it exactly like any other SDK capture. If dropping attachments whenever their parent's category is rate limited is the behavior you want, I think it belongs in RateLimiter for all captures rather than special-cased in OutboxSender. Happy to do that as a follow-up if you'd like.


📜 Description
OutboxSender.processEnvelopenow sends an outbox envelope's attachments in the same envelope as its event or transaction, instead of one standalone envelope per attachment. IfbeforeSend, an event processor or sampling drops the parent, its attachments are dropped with it.For an envelope with exactly one Event or Transaction item, the sender collects every attachment up front (so attachments before or after the parent both work), wraps each item's data in the existing
Attachment(Callable<byte[]>, filename, contentType, attachmentType, addToTransactions)constructor, and adds them to the hint forcaptureEvent/captureTransaction.SentryClientalready builds the combined envelope fromhint.getAttachments(), andaddToTransactionsis set for transaction parents sofilterForTransactionkeeps them. The hint's previous attachments are restored infinally, sinceHint.clear()does not clear attachments.Unchanged paths:
Grouped attachments now go through
SentryEnvelopeItem.fromAttachment, so they follow the configured per-attachmentmaxAttachmentSize. There is no aggregate envelope cap; the issue raises one as a proposal, and this PR does not add it.💡 Motivation and Context
Native crash attachments (for example
event.minidump) were ingested even when the event that owns them was filtered or sampled out, which produced orphaned attachments.Fixes #6067
💚 How did you test it?
New tests in
OutboxSenderTest.kt, several of them through a realSentryClient,JsonSerializerandEnvelopeReaderwith a recording transport:Commands (JDK 21):
./gradlew :sentry:test --tests="*OutboxSenderTest*": passes./gradlew :sentry:test --tests="*SentryClientTest*": passes./gradlew :sentry:spotlessCheck: passes./gradlew :sentry:updateKotlinAbi: no API file changes📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps
The changelog entry gets this PR's link once the number exists.
AI was used for assistance.