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()— parseserror.stackinto 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()andsanitizeError()
packages/core/src/v3/otel/utils.ts
sanitizeSpanError()now usestruncateStackandtruncateMessagefromerrors.tsinstead of duplicating truncation logic- Non-Error values (strings, JSON) capped at 5000 chars
packages/core/src/v3/tracer.ts
startActiveSpancatch block now delegates torecordSpanException()instead of callingspan.recordException()directly
Limits
| What | Limit | Rationale |
|---|---|---|
| Stack frames | 50 | Matches Sentry's STACKTRACE_FRAME_LIMIT |
| Top frames kept | 5 | Closest to throw site |
| Bottom frames kept | 45 | Entry points / framework frames |
| Per-line length | 1024 | Matches Sentry, prevents regex DoS |
| Message length | 1000 | Bounded but generous |
| Generic string (non-Error) | 5000 | Fallback 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)