microsoft/playwright · error · Error
Invalid timezone ID: ${contextOptions.timezoneId}
Error message
Invalid timezone ID: ${contextOptions.timezoneId} What it means
When a contextOptions.timezoneId is set, WebKit issues Page.setTimeZone; if the engine rejects the timezone string (unrecognized IANA zone), the .catch rewraps it as 'Invalid timezone ID: <id>'. WebKit only accepts valid IANA timezone identifiers.
Source
Thrown at packages/playwright-core/src/server/webkit/wkPage.ts:217
if (bootstrapScript.length)
promises.push(session.send('Page.setBootstrapScript', { source: bootstrapScript }));
this._page.frames().map(frame => frame.evaluateExpression(nullProgress, bootstrapScript).catch(e => {}));
if (contextOptions.bypassCSP)
promises.push(session.send('Page.setBypassCSP', { enabled: true }));
const emulatedSize = this._page.emulatedSize();
if (emulatedSize) {
promises.push(session.send('Page.setScreenSizeOverride', {
width: emulatedSize.screen.width,
height: emulatedSize.screen.height,
}));
}
promises.push(session.send('Network.setExtraHTTPHeaders', { headers: headersArrayToObject(this._calculateExtraHTTPHeaders(), false /* lowerCase */) }));
if (contextOptions.offline)
promises.push(session.send('Network.setEmulateOfflineState', { offline: true }));
promises.push(session.send('Page.setTouchEmulationEnabled', { enabled: !!contextOptions.hasTouch }));
if (contextOptions.timezoneId) {
promises.push(session.send('Page.setTimeZone', { timeZone: contextOptions.timezoneId }).
catch(e => { throw new Error(`Invalid timezone ID: ${contextOptions.timezoneId}`); }));
}
if (this._page.fileChooserIntercepted())
promises.push(session.send('Page.setInterceptFileChooserDialog', { enabled: true }));
promises.push(session.send('Page.overrideSetting', { setting: 'FullScreenEnabled', value: !contextOptions.isMobile }));
promises.push(session.send('Page.overrideSetting', { setting: 'NotificationsEnabled', value: !contextOptions.isMobile }));
promises.push(session.send('Page.overrideSetting', { setting: 'PointerLockEnabled', value: !contextOptions.isMobile }));
promises.push(session.send('Page.overrideSetting', { setting: 'InputTypeMonthEnabled', value: contextOptions.isMobile }));
promises.push(session.send('Page.overrideSetting', { setting: 'InputTypeWeekEnabled', value: contextOptions.isMobile }));
promises.push(session.send('Page.overrideSetting', { setting: 'FixedBackgroundsPaintRelativeToDocument', value: contextOptions.isMobile }));
promises.push(session.send('Page.overrideSetting', { setting: 'PushAPIEnabled', value: !contextOptions.isMobile }));
await Promise.all(promises);
}
private _initializeFrameSessions(frame: Protocol.Page.FrameResourceTree, promises: Promise<any>[]) {
const session = this._targetIdToFrameSession.get(`frame-${frame.frame.id}`);
if (session)
promises.push(session.initialize());
for (const childFrame of frame.childFrames || [])View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Use a canonical IANA timezone id, e.g. 'America/New_York', 'Europe/Berlin', 'UTC'.
- On Linux CI ensure the tzdata package is installed so the zone database is complete.
- Validate the id against Intl.supportedValuesOf('timeZone') (modern Node) before passing it.
Example fix
// before
const ctx = await browser.newContext({ timezoneId: 'EST' });
// after
const ctx = await browser.newContext({ timezoneId: 'America/New_York' }); Defensive patterns
Strategy: validation
Validate before calling
const known = new Set(typeof Intl !== 'undefined' && Intl.supportedValuesOf ? Intl.supportedValuesOf('timeZone') : ['UTC']);
function validTz(tz) { return !tz || known.has(tz); } Type guard
function isIanaTimezone(tz: string): boolean {
if (typeof Intl !== 'undefined' && Intl.supportedValuesOf) return Intl.supportedValuesOf('timeZone').includes(tz);
return tz === 'UTC' || tz.includes('/');
} Try / catch
try { await browser.newContext({ timezoneId }); }
catch (e) {
if (/Invalid timezone ID/.test(e.message)) await browser.newContext({ timezoneId: 'UTC' });
else throw e;
} Prevention
- Use canonical IANA ids (America/New_York, Europe/Berlin, UTC).
- Install tzdata on minimal Linux CI images.
When it happens
Trigger: Launching a context with newContext({ timezoneId: '...' }) where the value is misspelled, non-IANA, or not present in the OS tz database. Also contextOptions updates that re-apply an invalid zone.
Common situations: Typos like 'UTC+2' or 'EST' (use 'America/New_York'), 'GMT' variants, or zones absent on minimal CI images. Copying timezone strings from non-IANA sources.
Related errors
- Invalid timezone ID: ${timezoneId}
- Unknown permission: ${permission}
- WebKit on Windows has a minimal viewport of 250x240.
- Mouse wheel is not supported in mobile WebKit
- The page does not support tap. Use hasTouch context option t
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/c0fbaf13b7c2137a.
Report an issue: GitHub.