Suppress expired exec approval followup warnings (#66685)

* fix(agents): suppress expired approval followup warnings

* fix(agents): suppress expired approval followup warnings

---------

Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
This commit is contained in:
Paul Frederiksen
2026-06-30 21:39:06 -07:00
committed by GitHub
parent d0f655811c
commit d68ba5edc5
2 changed files with 37 additions and 0 deletions
@@ -167,6 +167,39 @@ describe("sendExecApprovalFollowupResult", () => {
);
});
it.each([
{
name: "direct gateway code",
error: Object.assign(new Error("approval not found"), {
gatewayCode: "APPROVAL_NOT_FOUND",
}),
},
{
name: "structured invalid-request details",
error: Object.assign(new Error("approval not found"), {
gatewayCode: "INVALID_REQUEST",
details: { reason: "APPROVAL_NOT_FOUND" },
}),
},
{
name: "legacy message-only error",
error: new Error("unknown or expired approval id"),
},
])("suppresses approval-not-found followup dispatch failures ($name)", async ({ error }) => {
sendExecApprovalFollowup.mockRejectedValue(error);
await sendExecApprovalFollowupResult(
{
approvalId: "approval-expired",
sessionKey: "agent:main:main",
},
"Exec finished",
{ sendExecApprovalFollowup, logWarn },
);
expect(logWarn).not.toHaveBeenCalled();
});
it("evicts oldest followup failure dedupe keys after reaching the cap", async () => {
sendExecApprovalFollowup.mockRejectedValue(new Error("Channel is required"));
const deps = { sendExecApprovalFollowup, logWarn };
@@ -5,6 +5,7 @@
*/
import crypto from "node:crypto";
import { resolveExpiresAtMsFromDurationMs } from "@openclaw/normalization-core/number-coercion";
import { isApprovalNotFoundError } from "../infra/approval-errors.js";
import { formatErrorMessage } from "../infra/errors.js";
import { buildExecApprovalUnavailableReplyPayload } from "../infra/exec-approval-reply.js";
import {
@@ -481,6 +482,9 @@ export async function sendExecApprovalFollowupResult(
}
: {}),
}).catch((error: unknown) => {
if (isApprovalNotFoundError(error)) {
return;
}
const message = formatErrorMessage(error);
const key = `${target.approvalId}:${message}`;
if (!rememberExecApprovalFollowupFailureKey(key)) {