toJSON(error: unknown): SerializedFailure
Converts a Failure (or any error) into plain JSON.
This exists because JSON.stringify(new Error('boom')) is {}: message and stack are
own-but-non-enumerable, and name lives on the prototype. Anything that ships an error
over a WebSocket, a postMessage, or an HTTP response body has to do this conversion —
the alternative is the silent data loss where a caught error arrives on the far side as an
empty object and every downstream error.code check reads undefined.
structuredClone handles native errors better than JSON does (it preserves name,
message, stack, and cause) but still drops the prototype and every own property you
added — so code and data would not survive it either. Use this, not structuredClone,
for Failures.
import * as Failure from './failure.ts'; const ws = { send(_data: string) {} }; // stands in for the run's WebSocket const failure = Failure.from(new Error('boom')); ws.send(JSON.stringify({ event: 'run-error', error: Failure.toJSON(failure) }));