grafana/k6 · error
unexpected type %T
Error message
unexpected type %T
What it means
fill() evaluates an injected script that must return one of the protocol strings 'done', 'needsinput', or 'error:...'. This error means the evaluation returned a non-string Go value (nil, bool, object), i.e. the injected-script contract was broken. This is an internal invariant failure (bug or version mismatch), not a wrong fill value.
Source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:270
}
func (h *ElementHandle) fill(_ context.Context, value string) error {
fn := `
(node, injected, value) => {
return injected.fill(node, value);
}
`
opts := evalOptions{
forceCallable: true,
returnByValue: true,
}
result, err := h.evalWithScript(h.ctx, opts, fn, value)
if err != nil {
return err
}
s, ok := result.(string)
if !ok {
return fmt.Errorf("unexpected type %T", result)
}
if s == resultNeedsInput {
if err := h.frame.page.Keyboard.InsertText(value); err != nil {
return fmt.Errorf("fill: %w", err)
}
} else if s != resultDone {
// Either we're done or an error happened (returned as "error:..." from JS)
return errorFromDOMError(s)
}
return nil
}
func (h *ElementHandle) focus(apiCtx context.Context, resetSelectionIfNotFocused bool) error {
fn := `
(node, injected, resetSelectionIfNotFocused) => {
return injected.focusNode(node, resetSelectionIfNotFocused);View on GitHub (pinned to 93accf6570)
Solutions
- Rebuild/upgrade with a single clean k6 (or xk6) version so the injected script and Go code match
- Re-query the element and retry fill after the page settles (wait for load state)
- Verify the target really is input/textarea/contenteditable to rule out the normal not-fillable path
- If reproducible on a stock k6 release, report it with the script and page URL
Example fix
// before
await handle.fill('hello'); // unexpected type <nil>
// after
const el = await page.waitForSelector('#name'); // fresh handle in a live context
await el.fill('hello'); Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the target is fillable before calling fill
const tag = await handle.evaluate((el) => el.tagName);
const editable = await handle.evaluate((el) => el.isContentEditable);
if (!['INPUT', 'TEXTAREA'].includes(tag) && !editable) {
throw new Error('target is not fillable');
} Try / catch
try {
await el.fill('hello');
} catch (e) {
if (String(e).includes('unexpected type')) {
// internal contract break: re-locate and retry once, then upgrade k6
await (await page.$(sel)).fill('hello');
} else { throw e; }
} Prevention
- Use matching k6/xk6 versions so the injected script is never stale
- Re-query elements before fill after navigation or re-renders
- Expect not-fillable errors as DOM messages, not 'unexpected type' — the latter means a bug
When it happens
Trigger: handle.fill(value) when the injected script returns undefined (execution context destroyed mid-eval) or when the bundled injected JS does not match the Go module, e.g. after a partial upgrade or a custom xk6 build mixing browser module versions.
Common situations: Custom xk6 builds bundling a stale injected script; page navigating while fill runs; rarely, a genuine k6 bug. Note: filling a non-fillable element normally yields 'element is not an <input>, <textarea> or [contenteditable] element' via errorFromDOMError, not this error.
Related errors
- checking element is in viewport: unexpected type %T
- value %v out of range for int32 type
- unexpected value %v of type %T
- parsing element fill options: %w
- parsing fill options: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/690cad54141e4329.
Report an issue: GitHub.