<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: v1.33.0</li>
<li>Operating System: macOS 13.2,</li>
<li>Browser: All</li>
<li>Other info:</li>
</ul>
<p dir="auto">An issue with custom Errors that have a getter for the message property.</p>
<p dir="auto">For some reason, Playwright is trying to set the message property of the error object, which is not allowed in some Error classes.<br>
So, this causes a TypeError to be thrown</p>
<h3 dir="auto">Source code</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I provided the exact source code that allows reproducing the issue locally.</li>
</ul>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import { test } from &quot;@playwright/test&quot;;
import { z } from &quot;zod&quot;;

class MyError extends Error {
  #issues: string[] = [];
  constructor(message: string) {
    super();
    this.name = &quot;MyError&quot;;
    this.#issues.push(message);
  }

  get message() {
    return this.#issues.join(&quot;\n&quot;);
  }
}

test(&quot;Error&quot;, async () =&gt; {
  // Error: Error message
  throw new Error(&quot;Error message&quot;);

  // TypeError: Cannot set property message of Error which has only a getter
  throw new MyError(&quot;Error message&quot;);

  z.object({
    name: z.string(),
  })
    // TypeError: Cannot set property message of [object Object] which has only a getter
    .parse({
      // throws ZodError with only message getter
      name: undefined,
    });
});
"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">test</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"@playwright/test"</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">z</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"zod"</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-smi">MyError</span> <span class="pl-k">extends</span> <span class="pl-smi">Error</span> <span class="pl-kos">{</span>
  #issues: <span class="pl-smi">string</span><span class="pl-kos">[</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">message</span>: <span class="pl-smi">string</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">super</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">name</span> <span class="pl-c1">=</span> <span class="pl-s">"MyError"</span><span class="pl-kos">;</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span>#issues<span class="pl-kos">.</span><span class="pl-en">push</span><span class="pl-kos">(</span><span class="pl-s1">message</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">get</span> <span class="pl-en">message</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span>#issues<span class="pl-kos">.</span><span class="pl-en">join</span><span class="pl-kos">(</span><span class="pl-s">"\n"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s">"Error"</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-c">// Error: Error message</span>
  <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">Error</span><span class="pl-kos">(</span><span class="pl-s">"Error message"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-c">// TypeError: Cannot set property message of Error which has only a getter</span>
  <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">MyError</span><span class="pl-kos">(</span><span class="pl-s">"Error message"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-s1">z</span><span class="pl-kos">.</span><span class="pl-en">object</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">name</span>: <span class="pl-s1">z</span><span class="pl-kos">.</span><span class="pl-en">string</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span>
    <span class="pl-c">// TypeError: Cannot set property message of [object Object] which has only a getter</span>
    <span class="pl-kos">.</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
      <span class="pl-c">// throws ZodError with only message getter</span>
      <span class="pl-c1">name</span>: <span class="pl-c1">undefined</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Link to the GitHub repository with the repro</strong></p>
<p dir="auto"><a href="https://github.com/doichev-kostia/playwright-typeerror">repo with an example</a></p>
<p dir="auto"><strong>Config file</strong></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// playwright.config.ts
export default defineConfig({
  testDir: &quot;./tests&quot;,
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: &quot;html&quot;,
  use: {
    trace: &quot;on-first-retry&quot;,
  },
  projects: [
    {
      name: &quot;chromium&quot;,
      use: { ...devices[&quot;Desktop Chrome&quot;] },
    },

    {
      name: &quot;firefox&quot;,
      use: { ...devices[&quot;Desktop Firefox&quot;] },
    },

    {
      name: &quot;webkit&quot;,
      use: { ...devices[&quot;Desktop Safari&quot;] },
    },
  ],
});
"><pre class="notranslate"><span class="pl-c">// playwright.config.ts</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-en">defineConfig</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">testDir</span>: <span class="pl-s">"./tests"</span><span class="pl-kos">,</span>
  <span class="pl-c1">fullyParallel</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
  <span class="pl-c1">forbidOnly</span>: <span class="pl-c1">!</span><span class="pl-c1">!</span><span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI</span><span class="pl-kos">,</span>
  <span class="pl-c1">retries</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI</span> ? <span class="pl-c1">2</span> : <span class="pl-c1">0</span><span class="pl-kos">,</span>
  <span class="pl-c1">workers</span>: <span class="pl-s1">process</span><span class="pl-kos">.</span><span class="pl-c1">env</span><span class="pl-kos">.</span><span class="pl-c1">CI</span> ? <span class="pl-c1">1</span> : <span class="pl-c1">undefined</span><span class="pl-kos">,</span>
  <span class="pl-c1">reporter</span>: <span class="pl-s">"html"</span><span class="pl-kos">,</span>
  <span class="pl-c1">use</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">trace</span>: <span class="pl-s">"on-first-retry"</span><span class="pl-kos">,</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-c1">projects</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">"chromium"</span><span class="pl-kos">,</span>
      <span class="pl-c1">use</span>: <span class="pl-kos">{</span> ...<span class="pl-s1">devices</span><span class="pl-kos">[</span><span class="pl-s">"Desktop Chrome"</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">"firefox"</span><span class="pl-kos">,</span>
      <span class="pl-c1">use</span>: <span class="pl-kos">{</span> ...<span class="pl-s1">devices</span><span class="pl-kos">[</span><span class="pl-s">"Desktop Firefox"</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>

    <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">"webkit"</span><span class="pl-kos">,</span>
      <span class="pl-c1">use</span>: <span class="pl-kos">{</span> ...<span class="pl-s1">devices</span><span class="pl-kos">[</span><span class="pl-s">"Desktop Safari"</span><span class="pl-kos">]</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Steps</strong></p>
<ul dir="auto">
<li>[Run the test]</li>
<li>[Get an error]</li>
</ul>
<p dir="auto"><strong>Expected</strong></p>
<p dir="auto">The playwright should not modify the original error message as some custom Errors do not provide a setter</p>
<p dir="auto"><strong>Actual</strong></p>
<p dir="auto"><code class="notranslate">TypeError: Cannot set property message of [object Object] which has only a getter</code><br>
<code class="notranslate">TypeError: Cannot set property message of Error which has only a getter</code></p>
<h3 dir="auto">System info</h3>
<ul dir="auto">
<li>Playwright Version: [v1.28.1]</li>
<li>Operating System: [Android]</li>
<li>Browser: [Chromium]</li>
<li>Other info: Using realMobile on BrowserStack</li>
</ul>
<h3 dir="auto">Source code</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I provided exact source code that allows reproducing the issue locally.</li>
</ul>




<p dir="auto"><strong>Config file</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export type BrowserStackTestOptions = {
  os: string;
  browser: string;
  browserName: string;
  browserVersion: string;
  osVersion: string;
  realMobile: boolean;
  deviceName: string;
};

export default defineConfig&lt;BrowserStackTestOptions&gt;({
  projects: [
    {
      name: 'browserstack.android-chrome-latest',
      use: {
        osVersion: '12.0',
        deviceName: 'Samsung Galaxy S22 Ultra',
        realMobile: true,
        browserName: 'chromium',
      },
    },
});"><pre class="notranslate"><span class="pl-c">// playwright.config.ts</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span> <span class="pl-s1">defineConfig</span><span class="pl-kos">,</span> <span class="pl-s1">devices</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'@playwright/test'</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-s1">type</span> <span class="pl-v">BrowserStackTestOptions</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-c1">os</span>: <span class="pl-s1">string</span><span class="pl-kos"></span><span class="pl-kos">;</span>
  browser: <span class="pl-s1">string</span><span class="pl-kos">;</span>
  browserName: <span class="pl-s1">string</span><span class="pl-kos">;</span>
  browserVersion: <span class="pl-s1">string</span><span class="pl-kos">;</span>
  osVersion: <span class="pl-s1">string</span><span class="pl-kos">;</span>
  realMobile: <span class="pl-s1">boolean</span><span class="pl-kos">;</span>
  deviceName: <span class="pl-s1">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-s1">defineConfig</span><span class="pl-c1">&lt;</span><span class="pl-v">BrowserStackTestOptions</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">projects</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span>
      <span class="pl-c1">name</span>: <span class="pl-s">'browserstack.android-chrome-latest'</span><span class="pl-kos">,</span>
      <span class="pl-c1">use</span>: <span class="pl-kos">{</span>
        <span class="pl-c1">osVersion</span>: <span class="pl-s">'12.0'</span><span class="pl-kos">,</span>
        <span class="pl-c1">deviceName</span>: <span class="pl-s">'Samsung Galaxy S22 Ultra'</span><span class="pl-kos">,</span>
        <span class="pl-c1">realMobile</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span>
        <span class="pl-c1">browserName</span>: <span class="pl-s">'chromium'</span><span class="pl-kos">,</span>
      <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span><span class="pl-kos"></span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Test file (self-contained)</strong></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const patchedCaps = { /* construct browserstack capabilites from BrowserStackTestOptions in the config.project */ };

it('should verify navigation url', async ({ }) =&gt; {
  const browser = await _android.connect(
      `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify(patchedCaps))}`
    );
  const context = await browser.launchBrowser();
  const page = await context.newPage();
  await page.route('https://x-cancel.examplethatdoesntexisthere.com/', async route =&gt; {
    route
      .fulfill({
        status: 200,
        body: '&lt;html&gt;&lt;/html&gt;',
      })
      .catch(() =&gt; {});
  });

  await page.goto('https://testurl.com/with-link');
  await page.getByRole('button', { name: 'navigate to x-cancel url' }).click();
  await page.waitForURL('https://x-cancel.examplethatdoesntexisthere.com');
  expect(await page.url()).toBe('https://x-cancel.examplethatdoesntexisthere.com');
});"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-s1">patchedCaps</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span> <span class="pl-c">/* construct browserstack capabilites from BrowserStackTestOptions in the config.project */</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-en">it</span><span class="pl-kos">(</span><span class="pl-s">'should verify navigation url'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">browser</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">_android</span><span class="pl-kos">.</span><span class="pl-en">connect</span><span class="pl-kos">(</span>
      <span class="pl-s">`wss://cdp.browserstack.com/playwright?caps=<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-en">encodeURIComponent</span><span class="pl-kos">(</span><span class="pl-c1">JSON</span><span class="pl-kos">.</span><span class="pl-en">stringify</span><span class="pl-kos">(</span><span class="pl-s1">patchedCaps</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">}</span></span>`</span>
    <span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">const</span> <span class="pl-s1">context</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">browser</span><span class="pl-kos">.</span><span class="pl-en">launchBrowser</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">const</span> <span class="pl-s1">page</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-en">newPage</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">route</span><span class="pl-kos">(</span><span class="pl-s">'https://x-cancel.examplethatdoesntexisthere.com/'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-s1">route</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-s1">route</span>
      <span class="pl-kos">.</span><span class="pl-en">fulfill</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
        <span class="pl-c1">status</span>: <span class="pl-c1">200</span><span class="pl-kos">,</span>
        <span class="pl-c1">body</span>: <span class="pl-s">'&lt;html&gt;&lt;/html&gt;'</span><span class="pl-kos">,</span>
      <span class="pl-kos">}</span><span class="pl-kos">)</span>
      <span class="pl-kos">.</span><span class="pl-en">catch</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s">'https://testurl.com/with-link'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">getByRole</span><span class="pl-kos">(</span><span class="pl-s">'button'</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">name</span>: <span class="pl-s">'navigate to x-cancel url'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">click</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">waitForURL</span><span class="pl-kos">(</span><span class="pl-s">'https://x-cancel.examplethatdoesntexisthere.com'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">url</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toBe</span><span class="pl-kos">(</span><span class="pl-s">'https://x-cancel.examplethatdoesntexisthere.com'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Steps</strong></p>
<ul dir="auto">
<li>[Run the test]</li>
<li>[Test will fail]</li>
</ul>
<p dir="auto"><strong>Expected</strong><br>
Should pass on Android Chrome the same way it does as on the desktop browsers.</p>
<p dir="auto"><strong>Actual</strong><br>
Test will fail with the following error:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="page.route: Unknown scheme for Params: Page.setNetworkInterceptionPatterns"><pre class="notranslate"><code class="notranslate">page.route: Unknown scheme for Params: Page.setNetworkInterceptionPatterns
</code></pre></div>
<p dir="auto">I'm guessing it would fail on local Android device as well, but I don't have device setup locally to test. I also was unable to test with the latest version of Playwright, because Browserstack currently only has version up to 1.28.1 on Android.</p>