mirror of https://github.com/openclaw/openclaw.git
gateway: narrow already-running exit code (#26718)
Co-authored-by: ImLukeF <92253590+ImLukeF@users.noreply.github.com>
This commit is contained in:
parent
2885c65c74
commit
0033f64e19
|
|
@ -228,16 +228,59 @@ describe("gateway-cli coverage", () => {
|
|||
});
|
||||
|
||||
it("prints stop hints on GatewayLockError when service is loaded", async () => {
|
||||
await withEnvOverride(
|
||||
{
|
||||
LAUNCH_JOB_LABEL: undefined,
|
||||
LAUNCH_JOB_NAME: undefined,
|
||||
XPC_SERVICE_NAME: undefined,
|
||||
OPENCLAW_LAUNCHD_LABEL: undefined,
|
||||
OPENCLAW_SYSTEMD_UNIT: undefined,
|
||||
INVOCATION_ID: undefined,
|
||||
SYSTEMD_EXEC_PID: undefined,
|
||||
JOURNAL_STREAM: undefined,
|
||||
OPENCLAW_WINDOWS_TASK_NAME: undefined,
|
||||
OPENCLAW_SERVICE_MARKER: undefined,
|
||||
OPENCLAW_SERVICE_KIND: undefined,
|
||||
},
|
||||
async () => {
|
||||
resetRuntimeCapture();
|
||||
serviceIsLoaded.mockResolvedValue(true);
|
||||
startGatewayServer.mockRejectedValueOnce(
|
||||
new GatewayLockError("another gateway instance is already listening"),
|
||||
);
|
||||
await expect(
|
||||
runGatewayCommand(["gateway", "--token", "test-token", "--allow-unconfigured"]),
|
||||
).rejects.toThrow("__exit__:0");
|
||||
|
||||
expect(startGatewayServer).toHaveBeenCalled();
|
||||
expect(runtimeErrors.join("\n")).toContain("Gateway failed to start:");
|
||||
expect(runtimeErrors.join("\n")).toContain("gateway stop");
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps exit 1 for gateway bind failures wrapped as GatewayLockError", async () => {
|
||||
resetRuntimeCapture();
|
||||
serviceIsLoaded.mockResolvedValue(true);
|
||||
startGatewayServer.mockRejectedValueOnce(
|
||||
new GatewayLockError("another gateway instance is already listening"),
|
||||
new GatewayLockError("failed to bind gateway socket on ws://127.0.0.1:18789: Error: boom"),
|
||||
);
|
||||
|
||||
await expectGatewayExit(["gateway", "--token", "test-token", "--allow-unconfigured"]);
|
||||
|
||||
expect(startGatewayServer).toHaveBeenCalled();
|
||||
expect(runtimeErrors.join("\n")).toContain("Gateway failed to start:");
|
||||
expect(runtimeErrors.join("\n")).toContain("gateway stop");
|
||||
expect(runtimeErrors.join("\n")).toContain("failed to bind gateway socket");
|
||||
});
|
||||
|
||||
it("keeps exit 1 for gateway lock acquisition failures", async () => {
|
||||
resetRuntimeCapture();
|
||||
serviceIsLoaded.mockResolvedValue(true);
|
||||
startGatewayServer.mockRejectedValueOnce(
|
||||
new GatewayLockError("failed to acquire gateway lock at /tmp/openclaw/gateway.lock"),
|
||||
);
|
||||
|
||||
await expectGatewayExit(["gateway", "--token", "test-token", "--allow-unconfigured"]);
|
||||
|
||||
expect(runtimeErrors.join("\n")).toContain("failed to acquire gateway lock");
|
||||
});
|
||||
|
||||
it("uses env/config port when --port is omitted", async () => {
|
||||
|
|
|
|||
|
|
@ -162,6 +162,23 @@ function resolveGatewayRunOptions(opts: GatewayRunOpts, command?: Command): Gate
|
|||
return resolved;
|
||||
}
|
||||
|
||||
function isGatewayLockError(err: unknown): err is GatewayLockError {
|
||||
return (
|
||||
err instanceof GatewayLockError ||
|
||||
(!!err && typeof err === "object" && (err as { name?: string }).name === "GatewayLockError")
|
||||
);
|
||||
}
|
||||
|
||||
function isHealthyGatewayLockError(err: unknown): boolean {
|
||||
if (!isGatewayLockError(err) || typeof err.message !== "string") {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
err.message.includes("gateway already running") ||
|
||||
err.message.includes("another gateway instance is already listening")
|
||||
);
|
||||
}
|
||||
|
||||
async function runGatewayCommand(opts: GatewayRunOpts) {
|
||||
const isDevProfile = process.env.OPENCLAW_PROFILE?.trim().toLowerCase() === "dev";
|
||||
const devMode = Boolean(opts.dev) || isDevProfile;
|
||||
|
|
@ -457,10 +474,7 @@ async function runGatewayCommand(opts: GatewayRunOpts) {
|
|||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof GatewayLockError ||
|
||||
(err && typeof err === "object" && (err as { name?: string }).name === "GatewayLockError")
|
||||
) {
|
||||
if (isGatewayLockError(err)) {
|
||||
const errMessage = describeUnknownError(err);
|
||||
defaultRuntime.error(
|
||||
`Gateway failed to start: ${errMessage}\nIf the gateway is supervised, stop it with: ${formatCliCommand("openclaw gateway stop")}`,
|
||||
|
|
@ -476,7 +490,7 @@ async function runGatewayCommand(opts: GatewayRunOpts) {
|
|||
// ignore diagnostics failures
|
||||
}
|
||||
await maybeExplainGatewayServiceStop();
|
||||
defaultRuntime.exit(1);
|
||||
defaultRuntime.exit(isHealthyGatewayLockError(err) ? 0 : 1);
|
||||
return;
|
||||
}
|
||||
defaultRuntime.error(`Gateway failed to start: ${String(err)}`);
|
||||
|
|
|
|||
Loading…
Reference in New Issue