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

  1. Use the exact same valid US-layout key name in up() as in down()
  2. Prefer press() so the pair always matches
  3. Validate the name against the US layout list before calling
  4. 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

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


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/449686a8cfdf2582. Report an issue: GitHub.