Bun C++ Exception Crash With PartyWebSocket Library
Hey there, fellow developers! Have you ever hit a wall where your seemingly robust application suddenly crashes with a cryptic C++ exception after running smoothly for a few minutes? If you're using Bun and the partysocket library's PartyWebSocket implementation, you're not alone. This article dives deep into a particular issue where Bun v1.3.5 consistently crashes with a "pure virtual method called" C++ exception, specifically when using PartyWebSocket. We'll explore the root cause, walk through the stack trace, and most importantly, provide a clear, easy-to-implement workaround using native WebSockets and lazy loading to keep your applications stable and reliable. Our goal is to transform a frustrating bug into a clear learning opportunity, helping you understand the intricacies of garbage collection in modern JavaScript runtimes like Bun.
Understanding the Bun C++ Exception Crash with PartyWebSocket
When working with Bun, the blazing-fast JavaScript runtime, we expect robust performance. However, some advanced scenarios, particularly those involving low-level interactions or specific libraries, can lead to unexpected issues. One such head-scratcher involves a persistent Bun C++ exception crash that occurs after just 3-4 minutes of runtime when an application utilizes PartyWebSocket from the partysocket library. This isn't just an occasional hiccup; it's a 100% reproducible crash that can halt your development or production environment in its tracks. The error message, "pure virtual method called" C++ exception, points to a fundamental problem within the underlying C++ runtime, specifically during critical operations like memory management.
The core of the issue lies within JavaScriptCore's parallel garbage collection (GC) mechanism. Bun, like many modern JavaScript runtimes, employs sophisticated GC to automatically reclaim memory. This process involves identifying objects that are no longer referenced by the application and marking them for deletion. The "parallel" aspect means that multiple threads are working simultaneously to speed up this crucial task. The stack trace, which we'll dissect shortly, clearly indicates that this crash happens precisely when the GC is attempting to mark WebCore/DOM objects. Now, why would PartyWebSocket be involved with WebCore/DOM objects? The partysocket library is designed to offer enhanced WebSocket functionality, often providing features like automatic reconnection, which might involve wrapping or extending the native WebSocket API. In doing so, it seems to create or interact with underlying WebCore/DOM objects in a way that becomes problematic when Bun's aggressive parallel GC kicks in. These objects, for reasons we'll explore, become invalid or are prematurely destroyed while the parallel GC threads are still trying to access and mark them. This invalid access leads directly to the pure virtual method called error, effectively bringing the entire Bun process down. The consistent timing of the crash—always within a few minutes—suggests a predictable cycle in Bun's GC schedule or resource lifecycle management. This specific interaction between partysocket's implementation details and Bun's garbage collection strategy is the crucial point of failure that we need to address for a stable application.
The Root Cause: WebCore/DOM Objects and Parallel GC
The root cause of this perplexing Bun crash is undeniably linked to the interaction between PartyWebSocket and Bun's underlying WebCore/DOM object management during parallel garbage collection. When the partysocket library initializes a PartyWebSocket instance, it appears to create or somehow reference internal WebCore/DOM objects that are managed by JavaScriptCore, Bun's JavaScript engine. These WebCore/DOM objects are fundamental components of web browsers and web-like environments, providing the building blocks for elements, events, and network communication. In Bun's context, even though it's a server-side runtime, it leverages many components from the WebKit ecosystem, which includes WebCore. This means that even in a server environment, concepts like DOMGCOutputConstraint (as seen in the stack trace) can come into play, especially when dealing with web APIs like WebSockets.
The critical issue arises when Bun's parallel garbage collection process begins its marking phase. During this phase, the GC attempts to traverse the object graph, identifying all reachable objects that should not be collected. If a WebCore/DOM object created or managed by PartyWebSocket is either prematurely destroyed or becomes corrupted while a parallel GC thread is actively trying to mark it, a