diff --git a/src/cli/daemon-cli/restart-health.test.ts b/src/cli/daemon-cli/restart-health.test.ts index 81f4964efa8..000a33686b6 100644 --- a/src/cli/daemon-cli/restart-health.test.ts +++ b/src/cli/daemon-cli/restart-health.test.ts @@ -572,6 +572,47 @@ describe("inspectGatewayRestart", () => { expect(sleep).toHaveBeenCalledTimes(185); }); + it("keeps waiting when the expected gateway version is not available yet", async () => { + const service = makeGatewayService({ status: "running", pid: 8000 }); + inspectPortUsage + .mockResolvedValueOnce({ + port: 18789, + status: "free", + listeners: [], + hints: [], + }) + .mockResolvedValueOnce({ + port: 18789, + status: "busy", + listeners: [{ pid: 8000, commandLine: "openclaw-gateway" }], + hints: [], + }); + probeGateway.mockResolvedValue({ + ok: true, + close: null, + server: { version: "2026.4.26", connId: "new" }, + }); + + const { waitForGatewayHealthyRestart } = await import("./restart-health.js"); + const snapshot = await waitForGatewayHealthyRestart({ + service, + port: 18789, + expectedVersion: "2026.4.26", + attempts: 4, + delayMs: 1_000, + }); + + expect(snapshot).toMatchObject({ + healthy: true, + gatewayVersion: "2026.4.26", + expectedVersion: "2026.4.26", + waitOutcome: "healthy", + elapsedMs: 1_000, + }); + expect(snapshot.versionMismatch).toBeUndefined(); + expect(sleep).toHaveBeenCalledTimes(1); + }); + it("annotates timeout waits when the health loop exhausts all attempts", async () => { const service = makeGatewayService({ status: "running", pid: 8000 }); inspectPortUsage.mockResolvedValue({ diff --git a/src/cli/daemon-cli/restart-health.ts b/src/cli/daemon-cli/restart-health.ts index be28920122b..6695d1e96c3 100644 --- a/src/cli/daemon-cli/restart-health.ts +++ b/src/cli/daemon-cli/restart-health.ts @@ -123,6 +123,9 @@ function applyExpectedVersion( if (snapshot.gatewayVersion === expectedVersion) { return { ...snapshot, expectedVersion }; } + if (snapshot.gatewayVersion == null) { + return { ...snapshot, healthy: false, expectedVersion }; + } return { ...snapshot, healthy: false,