grafana/k6 · error
'%s' is not a valid key for layout '%s'
Error message
'%s' is not a valid key for layout '%s'
What it means
Validation error from Keyboard.up(): the key is not present in the active layout's ValidKeys set, rejected locally before any CDP event. Identical condition to the down-path variant but formatted with '%s' quotes instead of %q — the two messages differ only in quoting style.
Source
Thrown at internal/js/modules/k6/browser/common/keyboard.go:144
WithCode(keyDef.Code).
WithLocation(keyDef.Location).
WithIsKeypad(keyDef.Location == 3).
WithText(text).
WithUnmodifiedText(text).
WithAutoRepeat(autoRepeat)
if err := action.Do(cdp.WithExecutor(k.ctx, k.session)); err != nil {
return fmt.Errorf("dispatching key event down: %w", err)
}
return nil
}
func (k *Keyboard) up(key string) error {
key = k.platformSpecificResolution(key)
keyInput := keyboardlayout.KeyInput(key)
if _, ok := k.layout.ValidKeys[keyInput]; !ok {
return fmt.Errorf("'%s' is not a valid key for layout '%s'", key, k.layoutName)
}
keyDef := k.keyDefinitionFromKey(keyInput)
k.modifiers &= ^k.modifierBitFromKeyName(keyDef.Key)
k.pressedKeysMu.Lock()
delete(k.pressedKeys, keyDef.KeyCode)
k.pressedKeysMu.Unlock()
action := input.DispatchKeyEvent(input.KeyUp).
WithModifiers(input.Modifier(k.modifiers)).
WithKey(keyDef.Key).
WithWindowsVirtualKeyCode(keyDef.KeyCode).
WithCode(keyDef.Code).
WithLocation(keyDef.Location)
if err := action.Do(cdp.WithExecutor(k.ctx, k.session)); err != nil {
return fmt.Errorf("dispatching key event up: %w", err)
}
View on GitHub (pinned to 93accf6570)
Solutions
- Use the exact same valid US-layout key name in up() as in down()
- Prefer press() so the pair always matches
- Validate the name against the US layout list before calling
- For non-layout characters use insertText()
Example fix
// before
await page.keyboard.down('Enter');
await page.keyboard.up('Return');
// after
await page.keyboard.press('Enter'); Defensive patterns
Strategy: validation
Validate before calling
if (!isValidKeyName(key)) throw new Error(`unsupported key in up(): ${key}`);
if (page.isClosed()) throw new Error('page closed before key up'); Type guard
function isValidKeyName(k) {
const VALID = new Set(['Enter','Backspace','Delete','Tab','Escape','ArrowUp','ArrowDown','ArrowLeft','ArrowRight','Home','End','PageUp','PageDown','Control','Shift','Alt','Meta']);
return VALID.has(k) || /^[a-zA-Z0-9]$/.test(k) || /^F([1-9]|1[0-2])$/.test(k);
} Try / catch
try {
await page.keyboard.up(key);
} catch (e) {
if (/is not a valid key for layout/.test(e.message)) {
throw new Error(`invalid key name '${key}' in up() — must match the down() name exactly`);
}
throw e;
} Prevention
- Use one constant for the key name in both down() and up()
- Prefer press() to eliminate name drift
- Apply the same alias map (Return→Enter) on the up path
When it happens
Trigger: keyboard.up('Return'), up('escape') (case-sensitive), up('é'); unbalanced pairs where down succeeded with one name and up is called with another (down('Enter'), up('Return')).
Common situations: Copy-pasted key names mixing conventions; typos or casing drift between the down and up calls; non-US layouts.
Related errors
- %q is not a valid key for layout %q
- sending key down: %w
- sending key up: %w
- pressing key: %w
- cannot do key down: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/449686a8cfdf2582.
Report an issue: GitHub.