mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-30 05:54:43 +00:00
fix(gateway): scope zod input mapping to explicit tool-input errors
This commit is contained in:
@@ -118,9 +118,19 @@ vi.mock("../agents/openclaw-tools.js", () => {
|
||||
throw toolAuthorizationError("mode forbidden");
|
||||
}
|
||||
if (mode === "zod") {
|
||||
const err = new Error("invalid tool payload") as Error & { issues?: unknown[] };
|
||||
const err = new Error("invalid tool payload") as Error & {
|
||||
issues?: unknown[];
|
||||
toolInputError?: boolean;
|
||||
};
|
||||
err.name = "ZodError";
|
||||
err.issues = [{ path: ["amount"], message: "Required", code: "invalid_type" }];
|
||||
err.toolInputError = true;
|
||||
throw err;
|
||||
}
|
||||
if (mode === "zod-internal") {
|
||||
const err = new Error("schema mismatch") as Error & { issues?: unknown[] };
|
||||
err.name = "ZodError";
|
||||
err.issues = [{ path: ["result"], message: "Invalid", code: "invalid_type" }];
|
||||
throw err;
|
||||
}
|
||||
if (mode === "crash") {
|
||||
@@ -546,7 +556,7 @@ describe("POST /tools/invoke", () => {
|
||||
expect(resMain.status).toBe(200);
|
||||
});
|
||||
|
||||
it("maps tool input/auth/schema errors to 400/403 and unexpected execution errors to 500", async () => {
|
||||
it("maps tool input/auth errors and explicit schema-input errors to 400/403", async () => {
|
||||
cfg = {
|
||||
...cfg,
|
||||
agents: {
|
||||
@@ -587,6 +597,17 @@ describe("POST /tools/invoke", () => {
|
||||
expect(zodBody.error?.type).toBe("tool_error");
|
||||
expect(zodBody.error?.message).toBe("invalid tool payload");
|
||||
|
||||
const internalZodRes = await invokeToolAuthed({
|
||||
tool: "tools_invoke_test",
|
||||
args: { mode: "zod-internal" },
|
||||
sessionKey: "main",
|
||||
});
|
||||
expect(internalZodRes.status).toBe(500);
|
||||
const internalZodBody = await internalZodRes.json();
|
||||
expect(internalZodBody.ok).toBe(false);
|
||||
expect(internalZodBody.error?.type).toBe("tool_error");
|
||||
expect(internalZodBody.error?.message).toBe("tool execution failed");
|
||||
|
||||
const crashRes = await invokeToolAuthed({
|
||||
tool: "tools_invoke_test",
|
||||
args: { mode: "crash" },
|
||||
|
||||
@@ -118,10 +118,14 @@ function resolveToolInputErrorStatus(err: unknown): number | null {
|
||||
return typeof status === "number" ? status : 400;
|
||||
}
|
||||
// Some tool implementations throw raw ZodError objects on malformed model/tool payloads.
|
||||
// Treat these as user-input validation failures (400), not internal server failures (500).
|
||||
// Only map to 400 when explicitly marked as tool-input validation; otherwise preserve 500.
|
||||
if (typeof err === "object" && err !== null) {
|
||||
const record = err as { name?: unknown; issues?: unknown };
|
||||
if (record.name === "ZodError" && Array.isArray(record.issues)) {
|
||||
const record = err as { name?: unknown; issues?: unknown; toolInputError?: unknown };
|
||||
if (
|
||||
record.name === "ZodError" &&
|
||||
Array.isArray(record.issues) &&
|
||||
record.toolInputError === true
|
||||
) {
|
||||
return 400;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user