{"record":{"id":"e9713d90c24ea196","repo":"grafana/k6","slug":"q-is-not-a-valid-key-for-layout-q","errorCode":null,"errorMessage":"%q is not a valid key for layout %q","messagePattern":"%q is not a valid key for layout %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/keyboard.go","lineNumber":105,"sourceCode":"\n// Type sends a press message to a session target for each character in text.\n// It delays the action if `Delay` option is specified.\n//\n// It sends an insertText message if a character is not among\n// valid characters in the keyboard's layout.\nfunc (k *Keyboard) Type(text string, kbdOpts KeyboardOptions) error {\n\tif err := k.typ(text, kbdOpts); err != nil {\n\t\treturn fmt.Errorf(\"typing text: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc (k *Keyboard) down(key string) error {\n\tkey = k.platformSpecificResolution(key)\n\n\tkeyInput := keyboardlayout.KeyInput(key)\n\tif _, ok := k.layout.ValidKeys[keyInput]; !ok {\n\t\treturn fmt.Errorf(\"%q is not a valid key for layout %q\", key, k.layoutName)\n\t}\n\n\tkeyDef := k.keyDefinitionFromKey(keyInput)\n\tk.modifiers |= k.modifierBitFromKeyName(keyDef.Key)\n\ttext := keyDef.Text\n\n\tk.pressedKeysMu.Lock()\n\t_, autoRepeat := k.pressedKeys[keyDef.KeyCode]\n\tk.pressedKeys[keyDef.KeyCode] = struct{}{}\n\tk.pressedKeysMu.Unlock()\n\n\tkeyType := input.KeyDown\n\tif text == \"\" {\n\t\tkeyType = input.KeyRawDown\n\t}\n\n\taction := input.DispatchKeyEvent(keyType).\n\t\tWithModifiers(input.Modifier(k.modifiers)).","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/keyboard.go#L87-L123","documentation":"Validation error from Keyboard.down(): the requested key string, after platformSpecificResolution, does not exist in the active keyboard layout's ValidKeys set (default layout 'us'). No CDP call is made — the request is rejected locally before any event is dispatched. This is the down-path variant using %q formatting.","triggerScenarios":"keyboard.down('Return') (correct name is 'Enter'); down('backspace') — names are case-sensitive; down('é') — not a US-layout key; down('Cmd') — not valid on the 'us' layout used by CDP (use 'Meta').","commonSituations":"Porting scripts from OS automation tools (xdotool 'Return', Windows VK names); non-US keyboard muscle memory; assuming lowercase modifier names work.","solutions":["Use the exact key names from the US layout: Enter, Backspace, Delete, Tab, Escape, ArrowUp/Down/Left/Right, Home, End, PageUp, PageDown, Control, Shift, Alt, Meta, F1-F12, single characters","Match casing exactly — 'control' is rejected, 'Control' is valid","For characters outside the layout use insertText()","Check the layout package's ValidKeys (keyboardlayout.GetKeyboardLayout('us')) for the authoritative list"],"exampleFix":"// before\nawait page.keyboard.down('Return');\nawait page.keyboard.up('Return');\n\n// after\nawait page.keyboard.down('Enter');\nawait page.keyboard.up('Enter');","handlingStrategy":"validation","validationCode":"const VALID_KEYS = new Set(['Enter','Backspace','Delete','Tab','Escape','ArrowUp','ArrowDown','ArrowLeft','ArrowRight','Home','End','PageUp','PageDown','Control','Shift','Alt','Meta',' ','Add','Subtract','Multiply','Divide','Separator','Decimal','F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12']);\nfunction isValidKeyName(k) {\n  return VALID_KEYS.has(k) || /^[a-zA-Z0-9]$/.test(k);\n}\nif (!isValidKeyName(key)) throw new Error(`unsupported key: ${key}`);","typeGuard":"function isValidKeyName(k) {\n  const VALID = new Set(['Enter','Backspace','Delete','Tab','Escape','ArrowUp','ArrowDown','ArrowLeft','ArrowRight','Home','End','PageUp','PageDown','Control','Shift','Alt','Meta']);\n  return VALID.has(k) || /^[a-zA-Z0-9]$/.test(k) || /^F([1-9]|1[0-2])$/.test(k);\n}","tryCatchPattern":"try {\n  await page.keyboard.down(key);\n} catch (e) {\n  if (/is not a valid key for layout/.test(e.message)) {\n    // map common OS names to CDP names and retry once\n    const alias = { Return: 'Enter', Backtab: 'Tab', Cmd: 'Meta', Ctrl: 'Control', Esc: 'Escape' }[key];\n    if (alias) await page.keyboard.down(alias); else throw e;\n  } else throw e;\n}","preventionTips":["Maintain an alias map from OS key names to CDP names (Return→Enter, Cmd→Meta)","Key names are case-sensitive: 'Control' not 'control'","Validate against the US-layout key set before sending"],"tags":["browser","keyboard","validation","input","user-error"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}