{"record":{"id":"8a0b6c2476fe871a","repo":"microsoft/playwright","slug":"no-mapping-for-text-i-found","errorCode":null,"errorMessage":"No mapping for ${text[i]} found","messagePattern":"No mapping for (.+?) found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/dispatchers/androidDispatcher.ts","lineNumber":119,"sourceCode":"  }\n\n  async swipe(params: channels.AndroidDeviceSwipeParams, progress: Progress) {\n    await this._object.send(progress, 'swipe', params);\n  }\n\n  async info(params: channels.AndroidDeviceInfoParams, progress: Progress): Promise<channels.AndroidDeviceInfoResult> {\n    const info = await this._object.send(progress, 'info', params);\n    fixupAndroidElementInfo(info);\n    return { info };\n  }\n\n  async inputType(params: channels.AndroidDeviceInputTypeParams, progress: Progress) {\n    const text = params.text;\n    const keyCodes: number[] = [];\n    for (let i = 0; i < text.length; ++i) {\n      const code = keyMap.get(text[i].toUpperCase());\n      if (code === undefined)\n        throw new Error('No mapping for ' + text[i] + ' found');\n      keyCodes.push(code);\n    }\n    await progress.race(Promise.all(keyCodes.map(keyCode => this._object.send(progress, 'inputPress', { keyCode }))));\n  }\n\n  async inputPress(params: channels.AndroidDeviceInputPressParams, progress: Progress) {\n    if (!keyMap.has(params.key))\n      throw new Error('Unknown key: ' + params.key);\n    await this._object.send(progress, 'inputPress', { keyCode: keyMap.get(params.key) });\n  }\n\n  async inputTap(params: channels.AndroidDeviceInputTapParams, progress: Progress) {\n    await this._object.send(progress, 'inputClick', params);\n  }\n\n  async inputSwipe(params: channels.AndroidDeviceInputSwipeParams, progress: Progress) {\n    await this._object.send(progress, 'inputSwipe', params);\n  }","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/dispatchers/androidDispatcher.ts#L101-L137","documentation":"Thrown by AndroidDeviceDispatcher.inputType() when a character in the requested text has no entry in the static keyMap (androidDispatcher.ts:224). inputType translates each character to an Android keycode one-by-one via keyMap.get(text[i].toUpperCase()); any character not present in the map aborts the whole call before any key is sent. The map covers A-Z, 0-9, a fixed set of symbols (* # , . - = ( ) \\ ; ` / @ and Tab/Space) and named keys — most punctuation, currency symbols, accented characters, and emoji are absent.","triggerScenarios":"Calling androidDevice.type(text) / the inputType RPC with text containing unsupported characters: '!', '$', '%', '^', '&', '_', '+', '[', ']', '{', '}', '|', ':', '\"', '<', '>', '?', uppercase accented letters, CJK, or emoji. toUpperCase() does not help because these chars have no mapping at any case.","commonSituations":"Typing passwords, emails with '+', prices with '$'/'%', code snippets with braces/brackets, or any non-ASCII content into an Android field via type(); data-driven tests that pass arbitrary user input straight to type().","solutions":["Filter or replace unsupported characters before calling type(); restrict input to the characters present in keyMap (A-Z, 0-9, space, tab, and the listed punctuation).","For arbitrary/Unicode text, set the field value directly via the element's setText / fill-style API or Android IME rather than keycode-by-keycode typing.","Pre-validate input against the supported set and fail fast in your test with a clear message rather than hitting the server-side throw."],"exampleFix":"// before: arbitrary text crashes on unsupported chars\nawait device.type(element, 'côte-d'ivoire $5.00');\n\n// after: set the field value directly for non-mapped text\nawait device.fill(element, 'côte-d'ivoire $5.00');\n// or sanitize to the mapped subset before typing\nconst safe = text.split('').filter(ch => androidKeyMap.has(ch.toUpperCase())).join('');\nawait device.type(element, safe);","handlingStrategy":"validation","validationCode":"// Validate input against the Android keyMap before typing.\nconst SUPPORTED = new Set('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789*#,-=()\\\\\\\\;`/@ \\t'.split(''));\nfunction isTypeableAndroid(text: string): boolean {\n  for (const ch of text) if (!SUPPORTED.has(ch.toUpperCase())) return false;\n  return true;\n}\nif (!isTypeableAndroid(text)) throw new Error(`Unsupported chars for Android type()`);","typeGuard":"function isAndroidTypeable(text: string): text is string {\n  const supported = new Set('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789*#,-=()\\\\\\\\;`/@ \\t');\n  return [...text].every(ch => supported.has(ch.toUpperCase()));\n}","tryCatchPattern":"try {\n  await device.fill(element, text);\n} catch (e) {\n  if (/No mapping for/.test(e.message)) {\n    // fall back to setting the field value directly via setText\n  } else throw e;\n}","preventionTips":["Keep a shared allowlist of Android-typeable characters and validate test inputs against it.","For arbitrary/Unicode text, prefer setText/fill over keycode typing.","Add a unit test that asserts your test-data strings are Android-typeable before running the device suite."],"tags":["android","input","text","keymap","validation"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}