diff --git a/src/daemon/diagnostics.test.ts b/src/daemon/diagnostics.test.ts index 70da0f80b05d..b7421c2935c4 100644 --- a/src/daemon/diagnostics.test.ts +++ b/src/daemon/diagnostics.test.ts @@ -36,4 +36,21 @@ describe("readLastGatewayErrorLine", () => { "gateway stdout current", ); }); + + it("prefers the current stderr error over a stale stdout match on linux", async () => { + const stateDir = makeTempStateDir(); + const homeDir = makeTempStateDir(); + const env = { HOME: homeDir, OPENCLAW_STATE_DIR: stateDir }; + const stateLogs = resolveGatewayLogPaths(env); + fs.mkdirSync(stateLogs.logDir, { recursive: true }); + // stderr carries the real, current failure; stdout carries an older matching + // line. On non-darwin platforms stderr is the strongest failure signal, so + // it must win instead of the stale stdout match. + fs.writeFileSync(stateLogs.stderrPath, "failed to bind gateway socket EADDRINUSE\n", "utf8"); + fs.writeFileSync(stateLogs.stdoutPath, "gateway start blocked: stale prior reason\n", "utf8"); + + await expect(readLastGatewayErrorLine(env, { platform: "linux" })).resolves.toBe( + "failed to bind gateway socket EADDRINUSE", + ); + }); }); diff --git a/src/daemon/diagnostics.ts b/src/daemon/diagnostics.ts index fc654a7f5c85..11bb0f64e0b8 100644 --- a/src/daemon/diagnostics.ts +++ b/src/daemon/diagnostics.ts @@ -40,7 +40,10 @@ export async function readLastGatewayErrorLine( : resolveGatewayLogPaths(env); const stderrRaw = readStderr ? await fs.readFile(stderrPath, "utf8").catch(() => "") : ""; const stdoutRaw = await fs.readFile(stdoutPath, "utf8").catch(() => ""); - const lines = [...stderrRaw.split(/\r?\n/), ...stdoutRaw.split(/\r?\n/)].map((line) => + // stderr is the strongest failure signal on non-darwin platforms, so place it + // last and scan from the end: the most recent stderr error line then wins over + // any (possibly stale) stdout match, matching the stderr-first fallback below. + const lines = [...stdoutRaw.split(/\r?\n/), ...stderrRaw.split(/\r?\n/)].map((line) => line.trim(), ); for (let i = lines.length - 1; i >= 0; i -= 1) {