Repository navigation
fix(attachments): prevent worker OOM on large event attachments - #1281
Merged
Merged
Conversation
betegon
marked this pull request as ready for review
September 2, 2026 19:23
betegon
force-pushed
the
fix/attachment-memory-limit
branch
from
September 2, 2026 19:38
98e894b to
56a2bc0
Compare
get_event_attachment crashed the Cloudflare Worker with "TypeError: Memory limit exceeded before EOF" on large attachments (Sentry issue MCP-SERVER-F5W: 161 events, 10 users, still firing across orgs). The download buffered the file ~4-5x in memory at once (Blob + arrayBuffer copy + base64 + JSON serialization), blowing the 128 MB isolate on the tens-of-MB tail (observed p99 ~16 MB, max ~38 MB). - Read the body once via arrayBuffer() and base64-encode from a Buffer view (bytesToBase64), roughly halving peak memory for the download path. - Cap inline downloads at 30 MB, gated on the already-fetched metadata size so the doomed request is never issued. - Oversized fallback resolves the objectstore presigned URL (302 Location) so agents can download directly with no credentials; legacy filestore attachments fall back to authenticated-download instructions. - Flag empty/truncated download bodies instead of emitting empty content. - Add coverage for text, oversized (objectstore + legacy), and empty-body attachments. Refs #1267 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
betegon
force-pushed
the
fix/attachment-memory-limit
branch
from
September 2, 2026 20:24
56a2bc0 to
c9a00c0
Compare
BYK
approved these changes
Sep 3, 2026
Address review feedback: give getEventAttachment's maxInlineBytes a default (DEFAULT_MAX_INLINE_ATTACHMENT_BYTES) so the size gate applies to every caller by default, and make it the single source of truth for the cap (the tool imports it for the message instead of redefining it). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
get_event_attachmentcrashes the Cloudflare Worker withTypeError: Memory limit exceeded before EOFwhen downloading large attachments. This is live and ongoing — Sentry issue MCP-SERVER-F5W: 161 events, 10 users, first seen 2026-02-22, still firing (last 2026-09-01) across orgs and clients (codex,cursor).Root cause: the download buffered the file ~4–5× in memory at once —
downloadResponse.blob()→blob.arrayBuffer()(a copy) → base64 (+33%) → JSON-serialization of the base64 — blowing the 128 MB isolate on the tens-of-MB tail. Real download sizes (90d span telemetry): p50 ≈ 90 KB, p99 ≈ 16 MB, max ≈ 38 MB.Refs #1267.
Changes
arrayBuffer()and base64-encode from aBufferview (bytesToBase64, no intermediateBlob/copy). Peak drops from ~4–5× to ~2× the payload.size, so an oversized attachment never issues the doomed download. 30 MB → ~80 MB peak, safely under the isolate; covers p99 and all observed traffic inline.302 Location— a self-authenticating, time-limited link that downloads with no credentials. Legacy filestore attachments (no redirect) fall back to authenticated-download instructions (sentry api …).Verification
Confirmed end-to-end against a real attachment (created in a test org):
302to an objectstore presigned URL.200+ the correct bytes.Also confirmed the download endpoint is auth-gated (401/403 unauthenticated) and validated the redirect vs. streaming behavior against
getsentry/sentrysource.Testing
pnpm tsc,biome lint/format,ast-grep, and the fullmcp-coresuite pass. New coverage: text (.log) attachments, oversized objectstore (→ presigned URL), oversized legacy (→ auth instructions), and empty body.🤖 Generated with Claude Code