From 1a3d44683159acfd420855b728d5b1f49d0de29d Mon Sep 17 00:00:00 2001 From: Raisal P Wardana <68648097+IEatCodeDaily@users.noreply.github.com> Date: Sat, 5 Sep 2026 21:15:26 +0700 Subject: [PATCH] fix(codex): format reset credit API errors (#3778) --- open-sse/services/usage/codex.js | 9 ++++++++- tests/unit/codex-reset-credits.test.js | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/open-sse/services/usage/codex.js b/open-sse/services/usage/codex.js index 64d3cbbc..67d91c4b 100644 --- a/open-sse/services/usage/codex.js +++ b/open-sse/services/usage/codex.js @@ -21,6 +21,13 @@ function toIsoDate(value) { return Number.isFinite(time) ? date.toISOString() : null; } +function errorMessage(value, fallback) { + if (!value) return fallback; + if (typeof value === "string") return value; + if (typeof value.message === "string") return value.message; + return JSON.stringify(value); +} + function getCodexAccountId(providerSpecificData) { return providerSpecificData?.workspaceId || providerSpecificData?.accountId || providerSpecificData?.chatgptAccountId || null; } @@ -162,7 +169,7 @@ export async function getCodexRateLimitResetCredits(accessToken, proxyOptions = } if (!response.ok) { - const message = data?.message || data?.error || data?.detail || `Codex reset credits API unavailable (${response.status}).`; + const message = errorMessage(data?.message || data?.error || data?.detail, `Codex reset credits API unavailable (${response.status}).`); throw new Error(message); } diff --git a/tests/unit/codex-reset-credits.test.js b/tests/unit/codex-reset-credits.test.js index c8b4c6fd..43846248 100644 --- a/tests/unit/codex-reset-credits.test.js +++ b/tests/unit/codex-reset-credits.test.js @@ -91,6 +91,17 @@ describe("Codex reset credits", () => { }); }); + it("surfaces structured upstream errors as readable messages", async () => { + mocks.proxyAwareFetch.mockResolvedValue({ + ok: false, + status: 403, + json: async () => ({ error: { message: "Reset credits are unavailable for this account" } }), + }); + + const { getCodexRateLimitResetCredits } = await import("../../open-sse/services/usage/codex.js"); + await expect(getCodexRateLimitResetCredits("token")).rejects.toThrow("Reset credits are unavailable for this account"); + }); + it("GET refreshes OAuth credentials before returning reset credit details", async () => { const connection = { id: "conn_1",