mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 00:16:29 +02:00
surface silent runtime failures as error events
AgentRuntime.trigger() wrapped its body in try/finally with no outer
catch. An inner catch around the streamAgent for-await only handled
AbortError and rethrew everything else. Call sites fire-and-forget
trigger (runs.ts:26,60,72), so any thrown error became an unhandled
promise rejection. The finally still ran and published
run-processing-end, but nothing told the renderer why — the chat
showed the spinner, then an empty assistant bubble.
Provider misconfig, invalid API keys, unknown model ids, streamText
setup throws, runsRepo.fetch or loadAgent failing, and provider
auth/rate-limit rejections on the first chunk all hit this path on a
first message. All invisible.
Add a top-level catch that formats the error to a string and emits a
{type: "error"} RunEvent via the existing runsRepo/bus path. The
renderer already renders those as a chat bubble plus toast
(App.tsx:2069) — no UI work needed.
No changes to the abort path: user-initiated stops still flow through
the existing inner catch and the signal.aborted branch that emits
run-stopped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
32b6b2f1c0
commit
c81d3cb27b
1 changed files with 13 additions and 0 deletions
|
|
@ -194,6 +194,19 @@ export class AgentRuntime implements IAgentRuntime {
|
|||
await this.runsRepo.appendEvents(runId, [stoppedEvent]);
|
||||
await this.bus.publish(stoppedEvent);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Run ${runId} failed:`, error);
|
||||
const message = error instanceof Error
|
||||
? (error.stack || error.message || error.name)
|
||||
: typeof error === "string" ? error : JSON.stringify(error);
|
||||
const errorEvent: z.infer<typeof RunEvent> = {
|
||||
runId,
|
||||
type: "error",
|
||||
error: message,
|
||||
subflow: [],
|
||||
};
|
||||
await this.runsRepo.appendEvents(runId, [errorEvent]);
|
||||
await this.bus.publish(errorEvent);
|
||||
} finally {
|
||||
this.abortRegistry.cleanup(runId);
|
||||
await this.runsLock.release(runId);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue