grafana/k6 · error

typing text: %w

Error message

typing text: %w

What it means

Wrapper returned by Keyboard.Type when typ() fails. typ() iterates each character: valid layout keys go through press() (down+up with optional per-character delay), everything else falls back to insertText(). The error wraps a canceled wait during Delay, a failed per-character press, or a failed insertText fallback.

Source

Thrown at internal/js/modules/k6/browser/common/keyboard.go:95

	return nil
}

// InsertText inserts a text without dispatching key events.
func (k *Keyboard) InsertText(text string) error {
	if err := k.insertText(text); err != nil {
		return fmt.Errorf("inserting text: %w", err)
	}
	return nil
}

// Type sends a press message to a session target for each character in text.
// It delays the action if `Delay` option is specified.
//
// It sends an insertText message if a character is not among
// valid characters in the keyboard's layout.
func (k *Keyboard) Type(text string, kbdOpts KeyboardOptions) error {
	if err := k.typ(text, kbdOpts); err != nil {
		return fmt.Errorf("typing text: %w", err)
	}
	return nil
}

func (k *Keyboard) down(key string) error {
	key = k.platformSpecificResolution(key)

	keyInput := keyboardlayout.KeyInput(key)
	if _, ok := k.layout.ValidKeys[keyInput]; !ok {
		return fmt.Errorf("%q is not a valid key for layout %q", key, k.layoutName)
	}

	keyDef := k.keyDefinitionFromKey(keyInput)
	k.modifiers |= k.modifierBitFromKeyName(keyDef.Key)
	text := keyDef.Text

	k.pressedKeysMu.Lock()
	_, autoRepeat := k.pressedKeys[keyDef.KeyCode]

View on GitHub (pinned to 93accf6570)

Solutions

  1. Compute total time: type() with delay d and n chars blocks ~ n*d ms — keep it well under the timeout option
  2. For pure text entry without key events, use insertText(text) once instead of per-character typing
  3. Ensure the page stays open and no navigation occurs while typing
  4. Catch and retry the full type() from a stable page state (input fields tolerate re-typing after clear())

Example fix

// before
await page.type('#msg', 'a very long status message', { delay: 500 }); // 500ms * ~28 chars

// after
await page.keyboard.insertText('a very long status message'); // no per-char delay
Defensive patterns

Strategy: validation

Validate before calling

const totalMs = text.length * (delayMs || 0) + text.length * 5; // heuristic per-char cost
if (totalMs > actionTimeoutMs * 0.8) {
  throw new Error('type() duration too close to timeout — lower delay or use insertText()');
}
if (page.isClosed()) throw new Error('page closed before type');

Try / catch

try {
  await page.keyboard.type(text, { delay });
} catch (e) {
  if (/typing text|pressing key|inserting text|context/.test(e.message)) {
    await page.$eval(sel, 'el => el.value = ""');
    await page.keyboard.type(text, { delay: 0 }); // retry faster from clean field
  } else throw e;
}

Prevention

When it happens

Trigger: type('héllo wörld', { delay: 100 }) where 'é'/'ö' take the insertText path and the session dies mid-string; a delay per character times the context out (delay * len > timeout); page closed while typing a long string.

Common situations: Typing long texts with per-character delay exceeding the browser action timeout; typing into a page whose beforeunload/navigation interrupts input; typing after the element was removed so the renderer target changed.

Related errors


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