Merged
Size
M
Change Breakdown
Bug Fix60%
Performance20%
Maintenance20%
#3405fix(core): truncate large error stacks and messages to prevent OOM

Error stack and message truncation added to prevent OOMs

Error serialization in the core package now limits stack traces to 50 frames and messages to 1,000 characters, preventing worker processes from crashing due to memory exhaustion.

Throwing errors with massive stack traces—such as those generated by chat agent hooks—could previously overwhelm worker processes, leading to Out-Of-Memory (OOM) crashes during error serialization. To prevent this, error stacks and messages are now aggressively truncated across the @trigger.dev/core package. Stack traces are capped at 50 frames, retaining the 5 closest to the throw site and 45 entry points, while individual stack lines and messages are limited to roughly 1,000 characters. This ensures that large errors can be safely serialized into OpenTelemetry spans and task objects without crashing the process, keeping the system stable while preserving the most critical debugging context.

View Original GitHub Description

Summary

Large error stacks and messages can OOM the worker process when serialized into OTel spans or TaskRunError objects. This was reported when throwing an error with a massive .stack property from a chat agent hook.

This adds frame-based stack truncation (similar to Sentry's approach) plus message length limits, applied consistently across all error serialization paths.

What changed

packages/core/src/v3/errors.ts

  • truncateStack() — parses error.stack into message lines + frame lines, caps at 50 frames (keep top 5 closest to throw + bottom 45 entry points, with "... N frames omitted ..." in between). Individual lines capped at 1024 chars.
  • truncateMessage() — caps error messages at 1000 chars
  • Applied in parseError() and sanitizeError()

packages/core/src/v3/otel/utils.ts

  • sanitizeSpanError() now uses truncateStack and truncateMessage from errors.ts instead of duplicating truncation logic
  • Non-Error values (strings, JSON) capped at 5000 chars

packages/core/src/v3/tracer.ts

  • startActiveSpan catch block now delegates to recordSpanException() instead of calling span.recordException() directly

Limits

WhatLimitRationale
Stack frames50Matches Sentry's STACKTRACE_FRAME_LIMIT
Top frames kept5Closest to throw site
Bottom frames kept45Entry points / framework frames
Per-line length1024Matches Sentry, prevents regex DoS
Message length1000Bounded but generous
Generic string (non-Error)5000Fallback for JSON/string errors in spans

Test plan

  • 17 unit tests in packages/core/test/errors.test.ts
  • E2E: threw a 300-frame / 5000-char-message error in the ai-chat reference app, verified truncated stack and message in span via get_span_details
  • Verified the run survived the error (no OOM, continued waiting for next message)
© 2026 · via Gitpulse