microsoft/playwright · error · Error

Cannot set cookies without an open page

Error message

Cannot set cookies without an open page

What it means

On the iOS Safari webview backend, cookie operations are scoped to an open page (the WKWebView only exposes document.cookie for the current page's domain). addCookies needs that page to inject cookies via the page protocol; with zero pages attached there is nowhere to write, so it throws. doGetCookies returns [] in the same situation, but addCookies cannot silently no-op.

Source

Thrown at packages/playwright-core/src/server/webkit/webview/wvBrowser.ts:337

    return network.filterCookies(cookies.map(c => {
      const copy: channels.NetworkCookie = {
        name: c.name,
        value: c.value,
        domain: c.domain,
        path: c.path,
        expires: c.session ? -1 : c.expires / 1000,
        httpOnly: c.httpOnly,
        secure: c.secure,
        sameSite: c.sameSite,
      };
      return copy;
    }), urls);
  }

  async addCookies(cookies: channels.SetNetworkCookie[]) {
    const page = this._cookiePage();
    if (!page)
      throw new Error('Cannot set cookies without an open page');
    const protocolCookies = network.rewriteCookies(cookies).map(c => {
      const session = c.expires === undefined || c.expires === -1;
      const cookie: Protocol.Page.Cookie = {
        name: c.name,
        value: c.value,
        domain: c.domain!,
        path: c.path!,
        expires: session ? 0 : c.expires! * 1000,
        session,
        httpOnly: !!c.httpOnly,
        secure: !!c.secure,
        sameSite: c.sameSite ?? 'Lax',
      };
      return cookie;
    });
    await page.setCookies(protocolCookies);
  }

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Ensure at least one page is open (context.pages().length > 0) before calling addCookies on a webview context.
  2. Navigate the existing page to the target domain first, then addCookies, then continue.
  3. If the page closed, reconnect or have the user reopen Safari before setting cookies.

Example fix

// before
await context.addCookies([{ name: 'sid', value: '1', domain: 'example.com', path: '/' }]);
// throws if no page attached

// after
const page = context.pages()[0];
if (page) {
  await page.goto('https://example.com');
  await context.addCookies([{ name: 'sid', value: '1', domain: 'example.com', path: '/' }]);
}
Defensive patterns

Strategy: validation

Validate before calling

function assertPageForCookies(context) {
  if (!context.pages().length) throw new Error('Open a page before adding cookies on a webview context.');
}
assertPageForCookies(context);
await context.addCookies(cookies);

Try / catch

try { await context.addCookies(cookies); }
catch (e) {
  if (/without an open page/i.test(String(e.message))) {
    await context.pages()[0]?.goto(targetUrl);
    await context.addCookies(cookies);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling context.addCookies([...]) on a webview context after all tabs/pages have closed (or before any page is attached); calling addCookies right after connect when the single tab detached.

Common situations: A test that sets up cookies before navigating, against an iOS Safari session where the initial tab disappeared; teardown ordering that closes the page before cookie setup of the next test.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/8e895e554b051825. Report an issue: GitHub.