diff --git a/app/src/adapters/gitea/client/transport.ts b/app/src/adapters/gitea/client/transport.ts index 2319c19..eec6fc1 100644 --- a/app/src/adapters/gitea/client/transport.ts +++ b/app/src/adapters/gitea/client/transport.ts @@ -95,7 +95,10 @@ export class GiteaTransport { attempt === attempts - 1 || (!retryable && lastError instanceof GiteaHttpError) ) { - throw lastError; + if (lastError instanceof GiteaHttpError) throw lastError; + throw new Error(`${method} ${this.apiBase}${path} failed`, { + cause: lastError, + }); } } await abortableDelay(1_000 * 2 ** attempt, this.signal); diff --git a/app/src/core/contracts.ts b/app/src/core/contracts.ts index 49d7033..4bc0672 100644 --- a/app/src/core/contracts.ts +++ b/app/src/core/contracts.ts @@ -123,7 +123,13 @@ export function statusMarker(issue: number, mode: Mode): Marker { } export function formatError(error: unknown): string { - if (error instanceof Error) return error.message; + if (error instanceof Error) { + if (error.cause === undefined) return error.message; + const cause = formatError(error.cause); + return cause && cause !== error.message + ? `${error.message}: ${cause}` + : error.message; + } return String(error); } diff --git a/app/src/tests/core/webhook.test.ts b/app/src/tests/core/webhook.test.ts index ec86e3d..686d627 100644 --- a/app/src/tests/core/webhook.test.ts +++ b/app/src/tests/core/webhook.test.ts @@ -6,13 +6,25 @@ import { findAcceptedPlan, } from "../../adapters/gitea/issues.js"; import type { GiteaComment, GiteaIssue } from "../../adapters/gitea/types.js"; -import { marker, sha256 } from "../../core/contracts.js"; +import { formatError, marker, sha256 } from "../../core/contracts.js"; import { parseAgentCommand, parseCommentPayload, verifyGiteaSignature, } from "../../core/webhook.js"; +test("formats nested transport error causes", () => { + const error = new Error("GET https://git.example/api/v1/user failed", { + cause: new TypeError("fetch failed", { + cause: new Error("getaddrinfo ENOTFOUND git.example"), + }), + }); + assert.equal( + formatError(error), + "GET https://git.example/api/v1/user failed: fetch failed: getaddrinfo ENOTFOUND git.example", + ); +}); + test("verifies the raw Gitea HMAC signature", () => { const body = Buffer.from('{"action":"created"}'); const signature = createHmac("sha256", "secret").update(body).digest("hex");