microsoft/playwright · error

mount() requires `baseURL` to point at the component…

Error message

mount() requires `baseURL` to point at the component gallery. Set it in your Playwright config.

What it means

The mount() fixture requires the baseURL config option to know where the component gallery page is served. If baseURL is not set, the fixture refuses to proceed and throws this error, because there is no gallery page to load the story into.

Solutions

  1. Set baseURL in playwright.config.ts: use: { baseURL: 'http://localhost:<gallery-port>' }.
  2. Start the gallery dev server and point baseURL at it.
  3. Use a project-specific config or CLI/fixture override that supplies the URL when running.

Example fix

// before (playwright.config.ts)
export default defineConfig({});
// after
export default defineConfig({ use: { baseURL: 'http://localhost:3000' } });
Defensive patterns

Strategy: validation

Validate before calling

if (!test.info().project.use.baseURL)
  throw new Error('Set use.baseURL in playwright.config.ts to the component gallery URL before using mount().');

Type guard

function hasBaseURL(use: PlaywrightTestOptions['use']): use is typeof use & { baseURL: string } {
  return typeof use.baseURL === 'string' && use.baseURL.length > 0;
}

Try / catch

try {
  const component = await mount('my-story');
} catch (e) {
  if ((e as Error).message.includes('baseURL')) {
    console.error('Add to playwright.config.ts: use: { baseURL: "http://localhost:3000" }');
  }
  throw e;
}

Prevention

When it happens

Trigger: Using the mount() fixture while the Playwright config lacks use.baseURL (and no CLI/fixture override supplies it).

Common situations: Component (gallery) tests added to a project originally configured only for plain e2e tests, config's use.baseURL removed or renamed, or CI running a config file that never sets baseURL.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of microsoft/playwright@f1d33b5029 (2026-09-21). Data as JSON: /api/errors/fe1b907fe9e19540. Report an issue: GitHub.

Appendix: source

Thrown at packages/playwright/src/index.ts:519

    let [page] = context.pages();
    if (!page)
      page = await context.newPage();
    await use(page);
  },

  mount: async ({ page, baseURL }, use) => {
    // exposeFunctions turns any callbacks in props into real, browser-callable
    // functions that dispatch back to the test.
    const callMount = (params: { story: string, props?: Record<string, any> }) =>
      page.evaluate(async p => {
        const w = window as any;
        if (typeof w.mount !== 'function')
          throw new Error('The gallery page does not define window.mount().');
        await w.mount(p);
      }, params, { exposeFunctions: true, serialize: ['Map', 'Set'] });
    await use(async (storyId: string, props?: any) => {
      if (!baseURL)
        throw new Error('mount() requires `baseURL` to point at the component gallery. Set it in your Playwright config.');
      // The gallery is a single page (served at baseURL) that exposes window.mount()/window.unmount().
      await page.goto(baseURL);
      await callMount({ story: storyId, props });
      // Points at the gallery root, scope the queries: component.getByRole(...).
      return Object.assign(page.locator('#root'), {
        // update() re-renders the same story with new props without navigating; if the gallery
        // reuses its root/instance, the framework reconciles and component state is preserved.
        update: (newProps?: any) => callMount({ story: storyId, props: newProps }),
        unmount: () => page.evaluate(async () => {
          await (window as any).unmount?.();
        }),
      });
    });
  },
});

type ScreenshotOption = PlaywrightWorkerOptions['screenshot'] | undefined;

View on GitHub (pinned to f1d33b5029)