diff --git a/src/app.ts b/src/app.ts index 322c6e8..f6a72e9 100644 --- a/src/app.ts +++ b/src/app.ts @@ -736,12 +736,12 @@ export async function buildApp(options: BuildAppOptions = {}): Promise { const status = error.statusCode !== undefined && error.statusCode >= 400 && error.statusCode < 600 ? error.statusCode : 500; const code = typeof error.code === "string" ? error.code : "error"; diff --git a/tests/app.test.ts b/tests/app.test.ts index 79c562c..de2a896 100644 --- a/tests/app.test.ts +++ b/tests/app.test.ts @@ -1224,7 +1224,7 @@ describe("Heimdall service", () => { // An answer never carries an input value. The canary stands in for whatever a // failure could quote: part of a misbound database URL in a pg or resolver -// error, a request body in a JSON parse error, a header or a path. +// error, a request body, a header, a path, or a 4xx error's own message. describe("error answers never echo an input", () => { const CANARY = "CANARY"; @@ -1276,6 +1276,19 @@ describe("error answers never echo an input", () => { expect(response.body).not.toContain(CANARY); }); + it("answers any other 4xx error by its code, not its message", async () => { + const app = await buildApp({ config: createTestConfig() }); + apps.push(app); + app.get("/v1/probe-4xx", async () => { + throw Object.assign(new Error(`refused ${CANARY}input`), { statusCode: 409, code: "PROBE_REFUSED" }); + }); + + const response = await app.inject({ method: "GET", url: "/v1/probe-4xx" }); + + expect(response.statusCode).toBe(409); + expect(response.json()).toEqual({ error: "invalid_request", code: "PROBE_REFUSED" }); + }); + it("answers an unsupported media type without quoting the header", async () => { const app = await buildApp({ config: createTestConfig() }); apps.push(app);