microsoft/playwright · error · Error
Unknown key: ${params.key}
Error message
Unknown key: ${params.key} What it means
Thrown by AndroidDeviceDispatcher.inputPress() when params.key is not a key in keyMap. Unlike inputType, inputPress checks keyMap.has(params.key) directly with NO toUpperCase(), so the lookup is case-sensitive: lowercase 'a' fails even though 'A' is mapped. Only the exact spellings in keyMap (capital letters A-Z, digits as strings, and named keys like 'Enter', 'Back', 'Home', 'VolumeUp', 'MediaPlayPause') are accepted.
Source
Thrown at packages/playwright-core/src/server/dispatchers/androidDispatcher.ts:127
fixupAndroidElementInfo(info);
return { info };
}
async inputType(params: channels.AndroidDeviceInputTypeParams, progress: Progress) {
const text = params.text;
const keyCodes: number[] = [];
for (let i = 0; i < text.length; ++i) {
const code = keyMap.get(text[i].toUpperCase());
if (code === undefined)
throw new Error('No mapping for ' + text[i] + ' found');
keyCodes.push(code);
}
await progress.race(Promise.all(keyCodes.map(keyCode => this._object.send(progress, 'inputPress', { keyCode }))));
}
async inputPress(params: channels.AndroidDeviceInputPressParams, progress: Progress) {
if (!keyMap.has(params.key))
throw new Error('Unknown key: ' + params.key);
await this._object.send(progress, 'inputPress', { keyCode: keyMap.get(params.key) });
}
async inputTap(params: channels.AndroidDeviceInputTapParams, progress: Progress) {
await this._object.send(progress, 'inputClick', params);
}
async inputSwipe(params: channels.AndroidDeviceInputSwipeParams, progress: Progress) {
await this._object.send(progress, 'inputSwipe', params);
}
async inputDrag(params: channels.AndroidDeviceInputDragParams, progress: Progress) {
await this._object.send(progress, 'inputDrag', params);
}
async screenshot(params: channels.AndroidDeviceScreenshotParams, progress: Progress): Promise<channels.AndroidDeviceScreenshotResult> {
return { binary: await this._object.screenshot(progress) };
}View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Use the exact Android key names from keyMap: single capital letters for letters ('A' not 'a'), string digits ('0'..'9'), and the named Android keys ('Enter', 'Back', 'Home', 'VolumeUp', 'MediaPlayPause', etc.).
- Uppercase single letters before pressing: press(ch.toUpperCase()).
- Replace desktop-only keys with the closest Android equivalent (e.g. 'Escape' -> 'Back', 'ArrowLeft/Right' -> 'DialLeft'/'DialRight' where appropriate) or omit them.
Example fix
// before: desktop key names / lowercase fail
await device.press('escape');
await device.press('a');
// after: exact Android keyMap names
await device.press('Back');
await device.press('A');
await device.press('Enter'); Defensive patterns
Strategy: validation
Validate before calling
const ANDROID_KEYS = new Set(['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9','Enter','Back','Home','VolumeUp','VolumeDown','Power','Camera','Clear','Tab','Space','Search','Menu']); // extend from keyMap
function isAndroidKey(key: string): boolean {
return ANDROID_KEYS.has(key);
}
if (!isAndroidKey(key)) throw new Error(`Unsupported Android key: ${key}`); Type guard
function isAndroidKeyName(key: string): key is string {
// Exact names from androidDispatcher keyMap; case-sensitive.
return ANDROID_KEYS.has(key);
} Prevention
- Use a constant set built from the keyMap in androidDispatcher.ts as the single source of truth for valid keys.
- Uppercase single letters before press(): key = ch.toUpperCase().
- Do not reuse desktop/Page-API key names ('Escape','ArrowDown','Control') for Android; map them explicitly to Android names.
When it happens
Trigger: Calling androidDevice.press(key) with a lowercase letter ('a'), an unmapped name ('Escape', 'Control', 'Alt', 'ArrowDown', 'F1'), a typo'd name ('Return' instead of 'Enter', 'HomeButton' instead of 'Home'), or any key not listed in the Android keyMap.
Common situations: Reusing keyboard key constants from the Page API (which accepts 'Escape', 'Control', arrows, lowercase) on Android; copy-pasting desktop key names into Android tests; assuming the Android key set matches USB HID / Playwright keyboard key codes.
Related errors
- No mapping for ${text[i]} found
- Unknown key: "${keyString}"
- No device with serial number '${options.deviceSerialNumber}'
- More than one device found. Please specify deviceSerialNumbe
- Unknown modifier ${modifier}
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/342906b146ca82a9.
Report an issue: GitHub.