fix(session): swallow onRecordError throw to avoid unhandled rejection (#106951)

* fix(session): swallow onRecordError throw to avoid unhandled rejection

* fix(session): settle async record error handlers

* fix(session): assimilate record handler results

---------

Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
moguangyu5-design
2026-07-14 12:45:57 +08:00
committed by GitHub
parent 05fb55eb7b
commit 8419675fa1
2 changed files with 42 additions and 1 deletions

View File

@@ -189,4 +189,39 @@ describe("recordInboundSession", () => {
expect(route.sessionKey).toBe("agent:main:main");
expect(route.createIfMissing).toBe(false);
});
it.each([
{
name: "throws synchronously",
handler: (_err: unknown): void => {
throw new Error("handler failed");
},
},
{
name: "returns a rejected promise",
handler: ((_err: unknown) => Promise.reject(new Error("handler failed"))) as (
_err: unknown,
) => void,
},
])("settles the tracked meta task when onRecordError $name", async ({ handler }) => {
const recordError = new Error("db failed");
recordSessionMetaFromInboundMock.mockRejectedValueOnce(recordError);
const onRecordError = vi.fn(handler);
let trackedMetaTask: Promise<unknown> | undefined;
await recordInboundSession({
storePath: "/tmp/openclaw-session-store.json",
sessionKey: "agent:main:demo-channel:1234:thread:42",
ctx,
onRecordError,
trackSessionMetaTask: (task) => {
trackedMetaTask = task;
},
});
expect(trackedMetaTask).toBeDefined();
await expect(trackedMetaTask).resolves.toBeUndefined();
expect(onRecordError).toHaveBeenCalledTimes(1);
expect(onRecordError).toHaveBeenCalledWith(recordError);
});
});

View File

@@ -48,7 +48,13 @@ export async function recordInboundSession(params: {
groupResolution,
createIfMissing,
})
.catch(params.onRecordError);
.catch(async (err: unknown) => {
try {
await Promise.resolve(params.onRecordError(err));
} catch {
// Error reporting must not reject the detached metadata task.
}
});
params.trackSessionMetaTask?.(metaTask);
void metaTask;