SeleniumHQ/selenium · error · InvalidArgumentError

key input is not a single code point: ${key}

Error message

key input is not a single code point: ${key}

What it means

Thrown by the internal checkCodePoint() helper when a key argument passed to a keyboard input action does not reduce to exactly one Unicode code point after NFC normalization. The WebDriver input protocol operates on single code units/code points, so multi-character keys are rejected at argument validation time. It is an InvalidArgumentError (HTTP 400 / invalid argument wire-level error), surfaced through selenium-webdriver's input device layer.

Source

Thrown at javascript/selenium-webdriver/lib/input.js:258

}

/**
 * @param {(string|Key|number)} key
 * @return {string}
 * @throws {!(InvalidArgumentError|RangeError)}
 */
function checkCodePoint(key) {
  if (typeof key === 'number') {
    return String.fromCodePoint(key)
  }

  if (typeof key !== 'string') {
    throw new InvalidArgumentError(`key is not a string: ${key}`)
  }

  key = key.normalize()
  if (Array.from(key).length !== 1) {
    throw new InvalidArgumentError(`key input is not a single code point: ${key}`)
  }
  return key
}

/**
 * Keyboard input device.
 *
 * @final
 * @see <https://www.w3.org/TR/webdriver/#dfn-key-input-source>
 */
class Keyboard extends Device {
  /** @param {string} id the device ID. */
  constructor(id) {
    super(Device.Type.KEY, id)
  }

  /**
   * Generates a key down action.

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Split the input into individual code points and iterate: [...str] in JS yields code points; feed one per action.
  2. Use String.fromCodePoint(codePointNumber) when you have a numeric code point, or pass the number directly (the helper accepts numbers).
  3. Verify the value with [...key].length === 1 before building the action; log the offending key.
  4. If you genuinely need a multi-character sequence, send each as a separate key action or use element.sendKeys(text) which handles sequences.
  5. Check that you are not accidentally passing a Key.* constant that is itself multi-codepoint (rare, but possible with custom constants).

Example fix

// before
await driver.actions().keyDown('ab').perform(); // throws

// after
for (const ch of [...'ab']) {
  await driver.actions().keyDown(ch).keyUp(ch).perform();
}
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleCodePoint(key) {
  if (typeof key === 'number') return; // number is accepted by the helper
  if (typeof key !== 'string') throw new TypeError('key must be string or number');
  const norm = key.normalize();
  if ([...norm].length !== 1) {
    throw new Error(`key is not a single code point: ${JSON.stringify(key)}`);
  }
}
// call before actions.keyDown(key) etc.

Type guard

function isSingleCodePoint(key) {
  return typeof key === 'number' || (typeof key === 'string' && [...key.normalize()].length === 1);
}

Try / catch

try {
  await driver.actions().keyDown(maybeBadKey).perform();
} catch (e) {
  if (e.name === 'InvalidArgumentError' && /single code point/.test(e.message)) {
    // split into code points and retry each
    for (const ch of [...maybeBadKey.normalize()]) {
      await driver.actions().keyDown(ch).keyUp(ch).perform();
    }
  } else throw e;
}

Prevention

When it happens

Trigger: Calling actions.keyDown(key)/keyUp(key)/sendKeys with a string that contains more than one code point (e.g. 'ab', an emoji+VS16 sequence, or a grapheme cluster that stays multi-codepoint after normalize()). Also triggered when a key value resolves to an empty string or a multi-codepoint Key constant is misused. Single characters like 'a', a surrogate-pair emoji that is exactly one code point, or a numeric code point (e.g. 0x1F600) pass.

Common situations: Passing the user's typed text as a single 'key' instead of one character at a time; copy-pasting a key from a doc that included a combining mark; sending a multi-codepoint symbol (e.g. flags '🇺🇸' = two regional indicators) as a keystroke; version upgrades where Key.* constants changed representation.

Related errors


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/382b1095f885d042. Report an issue: GitHub.