microsoft/playwright · error · Error
"isMobile" option is not supported with null "viewport"
Error message
"isMobile" option is not supported with null "viewport"
What it means
`validateBrowserContextOptions` rejects `noDefaultViewport: true` combined with `isMobile: true`. Mobile emulation needs a viewport to apply the mobile layout metrics.
Solutions
- Remove `isMobile` when using `noDefaultViewport`
- Or set an explicit viewport to enable mobile emulation
Example fix
// before
await browser.newContext({ viewport: null, isMobile: true });
// after
await browser.newContext({ viewport: { width: 375, height: 667 }, isMobile: true }); Defensive patterns
Strategy: validation
Validate before calling
const nullVp = opts.viewport === null || !!opts.noDefaultViewport;
if (nullVp && !!opts.isMobile) {
throw new Error('isMobile requires an explicit viewport; remove noDefaultViewport or unset isMobile.');
} Prevention
- Mobile emulation requires a viewport
- Avoid reusing device presets that set isMobile when going viewport-less
- Validate context options centrally before launch
When it happens
Trigger: `browser.newContext({ noDefaultViewport: true, isMobile: true })` or `{ viewport: null, isMobile: true }`.
Common situations: Combining desktop/windowed mode (null viewport) with mobile emulation flags; partial config merges that keep isMobile from a device-preset.
Related errors
- "deviceScaleFactor" option is not supported with null…
- Invalid resolution format: use
- Browser userDataDir is not supported in isolated mode.
- Cannot use --mobile together with --device, pick one.
- clientCertificates.origin is required
AI-assisted analysis of microsoft/playwright@f1d33b5029 (2026-08-12).
Data as JSON: /api/errors/9537796fccdcb98c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/playwright-core/src/server/browserContext.ts:774
addRouteInFlight(route: network.Route) {
this._routesInFlight.add(route);
}
removeRouteInFlight(route: network.Route) {
this._routesInFlight.delete(route);
}
async notifyRoutesInFlightAboutRemovedHandler(handler: network.RouteHandler): Promise<void> {
await Promise.all([...this._routesInFlight].map(route => route.removeHandler(handler)));
}
}
export function validateBrowserContextOptions(options: types.BrowserContextOptions, browserOptions: BrowserOptions) {
if (options.noDefaultViewport && options.deviceScaleFactor !== undefined)
throw new Error(`"deviceScaleFactor" option is not supported with null "viewport"`);
if (options.noDefaultViewport && !!options.isMobile)
throw new Error(`"isMobile" option is not supported with null "viewport"`);
if (options.acceptDownloads === undefined && browserOptions.name !== 'electron')
options.acceptDownloads = 'accept';
// Electron requires explicit acceptDownloads: true since we wait for
// https://github.com/electron/electron/pull/41718 to be widely shipped.
// In 6-12 months, we can remove this check.
else if (options.acceptDownloads === undefined && browserOptions.name === 'electron')
options.acceptDownloads = 'internal-browser-default';
if (!options.viewport && !options.noDefaultViewport)
options.viewport = { width: 1280, height: 720 };
if (options.proxy)
options.proxy = normalizeProxySettings(options.proxy);
if (options.recordVideo?.fps !== undefined && options.recordVideo.fps <= 0)
throw new Error(`"recordVideo.fps" must be a positive number, got ${options.recordVideo.fps}`);
verifyGeolocation(options.geolocation);
}
export function findMatchingHttpCredentials(credentials: HttpCredentials[] | undefined, url: string): HttpCredentials | undefined {
const origin = new URL(url).origin.toLowerCase();View on GitHub (pinned to f1d33b5029)