From ed418d56968a8aff122ac6f94f6db59f344505f8 Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Wed, 9 Sep 2026 01:29:17 +0700 Subject: [PATCH] fix(codex): treat a literal null from the CLI as an empty list, not a 500 --- server/__tests__/codex-cli.test.js | 13 +++++++++++++ server/lib/codex-cli.js | 6 ++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/server/__tests__/codex-cli.test.js b/server/__tests__/codex-cli.test.js index 2f60de0d..43ea15a6 100644 --- a/server/__tests__/codex-cli.test.js +++ b/server/__tests__/codex-cli.test.js @@ -321,6 +321,19 @@ describe("codex-cli run outcomes", () => { } }); + it("treats a literal `null` on stdout as an empty list, not a crash", async () => { + // `null` is valid JSON, so it parses and slips past the unparseable-output + // guard. Reading `.installed` off it would surface as a 500 from a route + // whose whole contract is that CLI output never produces one. + const restore = stubCodex("echo null"); + try { + assert.deepEqual((await cli.pluginList()).data, []); + assert.deepEqual((await cli.marketplaceList()).data, []); + } finally { + restore(); + } + }); + it("unwraps `codex plugin marketplace list --json`'s {marketplaces} object into a bare array", async () => { const restore = stubCodex(`cat <<'JSON'\n{"marketplaces":[{"name":"sg"}]}\nJSON`); try { diff --git a/server/lib/codex-cli.js b/server/lib/codex-cli.js index 49e916a0..eaae883d 100644 --- a/server/lib/codex-cli.js +++ b/server/lib/codex-cli.js @@ -258,8 +258,10 @@ async function mcpRemove(name) { */ async function pluginList() { const result = await runCodex(["plugin", "list", "--json"]); + // `data` is null when stdout was the literal `null` — JSON that parses to + // nothing. Guard it: a CLI's output must never reach the route as a 500. if (result.data !== undefined && !Array.isArray(result.data)) { - result.data = Array.isArray(result.data.installed) ? result.data.installed : []; + result.data = Array.isArray(result.data?.installed) ? result.data.installed : []; } return result; } @@ -283,7 +285,7 @@ async function pluginRemove(spec) { async function marketplaceList() { const result = await runCodex(["plugin", "marketplace", "list", "--json"]); if (result.data !== undefined && !Array.isArray(result.data)) { - result.data = Array.isArray(result.data.marketplaces) ? result.data.marketplaces : []; + result.data = Array.isArray(result.data?.marketplaces) ? result.data.marketplaces : []; } return result; }