diff --git a/src/browser/server-context.remote-tab-ops.test.ts b/src/browser/server-context.remote-tab-ops.test.ts index 74f2adcbe3f..3e4a074f4bd 100644 --- a/src/browser/server-context.remote-tab-ops.test.ts +++ b/src/browser/server-context.remote-tab-ops.test.ts @@ -447,6 +447,42 @@ describe("browser server-context tab selection state", () => { ); }); + it("does not fail tab open when managed-tab cleanup list fails", async () => { + vi.spyOn(cdpModule, "createTargetViaCdp").mockResolvedValue({ targetId: "NEW" }); + + let listCount = 0; + const fetchMock = vi.fn(async (url: unknown) => { + const value = String(url); + if (value.includes("/json/list")) { + listCount += 1; + if (listCount === 1) { + return { + ok: true, + json: async () => [ + { + id: "NEW", + title: "New Tab", + url: "http://127.0.0.1:3009", + webSocketDebuggerUrl: "ws://127.0.0.1/devtools/page/NEW", + type: "page", + }, + ], + } as unknown as Response; + } + throw new Error("/json/list timeout"); + } + throw new Error(`unexpected fetch: ${value}`); + }); + + global.fetch = withFetchPreconnect(fetchMock); + const state = makeState("openclaw"); + const ctx = createBrowserRouteContext({ getState: () => state }); + const openclaw = ctx.forProfile("openclaw"); + + const opened = await openclaw.openTab("http://127.0.0.1:3009"); + expect(opened.targetId).toBe("NEW"); + }); + it("blocks unsupported non-network URLs before any HTTP tab-open fallback", async () => { const fetchMock = vi.fn(async () => { throw new Error("unexpected fetch"); diff --git a/src/browser/server-context.ts b/src/browser/server-context.ts index 244d2f196c6..b5676d56396 100644 --- a/src/browser/server-context.ts +++ b/src/browser/server-context.ts @@ -143,7 +143,9 @@ function createProfileContext( return; } - const pageTabs = (await listTabs()).filter((tab) => (tab.type ?? "page") === "page"); + const pageTabs = await listTabs() + .then((tabs) => tabs.filter((tab) => (tab.type ?? "page") === "page")) + .catch(() => [] as BrowserTab[]); if (pageTabs.length <= MAX_MANAGED_BROWSER_PAGE_TABS) { return; }