Bun error tracking your coding agent can read
Updated 2026-11-07
When a route in Bun.serve throws, Bun calls the server's error() hook, and without one the stack trace only reaches the terminal. The Runheed SDK runs on Bun as it is, so one call in error() reports every route's exceptions, and the SDK also reports uncaught exceptions and unhandled rejections elsewhere in the process. It sends events in batches, so the server flushes before it stops on a deploy. Your coding agent then reads the error and the stack trace over MCP.
Set it up
1.Install the SDK and put your project DSN in RUNHEED_DSN. Bun reads .env by itself; on a host, add it to the service's environment variables.
terminalbashbun add https://runheed.com/dl/runheed-0.1.5.tgz2.Initialize once, report from error(), and flush on SIGTERM, which hosts send before they replace the process on a deploy. A route that catches its own errors can report them with the request.
server.tstypescriptimport runheed from 'runheed'; runheed.init({ dsn: process.env.RUNHEED_DSN!, environment: process.env.ENVIRONMENT ?? 'production' }); const server = Bun.serve({ port: Number(process.env.PORT ?? 3000), routes: { '/api/carts/:id': async (req) => { // ...your code return Response.json({ ok: true, cartId: req.params.id }); }, '/api/checkout': { POST: async (req) => { try { const { cartId } = (await req.json()) as { cartId: string }; // ...your code return Response.json({ ok: true, cartId }); } catch (err) { runheed.captureException(err as Error, { method: req.method, url: req.url }); return Response.json({ error: 'Checkout failed' }, { status: 500 }); } }, }, }, fetch() { return new Response('Not found', { status: 404 }); }, // Bun calls this when a route or fetch() throws. error(error) { runheed.captureException(error); return new Response('Internal error', { status: 500 }); }, }); // The SDK batches events for up to 5 seconds. Send them before the process stops. process.on('SIGTERM', async () => { await server.stop(); await runheed.flush(); process.exit(0); });3.Deploy, then connect your agent with the server URL and a sign-in (Claude Code shown; Cursor, claude.ai and ChatGPT take the same URL).
terminalbashclaude mcp add --transport http runheed https://runheed.com/api/mcp
The npm and PyPI releases are not out yet, so these commands install the same package files straight from runheed.com. Nothing else changes when the registry versions ship.
What it catches
- Any exception thrown in a Bun.serve route or fetch handler, with the stack trace
- Uncaught exceptions and unhandled promise rejections outside requests, such as in timers and startup code
- Errors you report yourself with captureException and the context you pass, such as the method and URL
What it does not do
- error() receives the error but not the request, so the method and URL are only attached where you catch and report the error yourself
- WebSocket handlers have their own error() in the websocket option; call captureException there too
- A process killed with SIGKILL or by running out of memory loses events still waiting in the batch
- Browser errors are not captured; there is no browser SDK yet
Then ask your agent
> what broke in production since the last deploy? fix the top one and resolve it with the commit hash
Connect Runheed first: Claude Code, Cursor or another client. Then see how the agent fixes and resolves an error.
Common Bun (Bun.serve) errors
- TypeError: Cannot read properties of undefined (reading 'x')
- [UnhandledPromiseRejection: This error originated either by throwing inside of an async...
- SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
- TypeError: fetch failed
- ZodError: [ { "expected": "string", "code": "invalid_type", "path": [ "email" ], "messa...
- Access to fetch at 'https://api.example.com/orders' from origin 'https://app.example.co...