grafana/k6 · error
setting input files
Error message
setting input files: %w
What it means
Thrown by the k6 browser module's ElementHandle.setInputFiles(). It wraps any failure of the setInputFiles action: timeout, element detached, or the injected script returning a DOM error — most typically 'node is not an input[type=file] element' (error:notfile) or 'non-multiple file input can only accept single file' (error:notmultiplefileinput).
Solutions
- Target the real file input: const input = await page.waitForSelector('input[type=file]') — often hidden, so use page.waitForSelector with state 'attached' and then call setInputFiles (it works on hidden inputs).
- Pass exactly one file when the input lacks the multiple attribute.
- Re-query the handle right before the call so it is attached to the current DOM.
- Increase the timeout: el.setInputFiles(files, { timeout: '60s' }).
Example fix
// before
const btn = await page.$('.upload-button');
await btn.setInputFiles([{ name: 'a.png', mimeType: 'image/png', data: ... }]); // not a file input
// after
const input = await page.waitForSelector('input[type="file"]');
await input.setInputFiles([{ name: 'a.png', mimeType: 'image/png', data: pngBytes }], { timeout: '30s' }); Defensive patterns
Strategy: validation
Validate before calling
const isFileInput = await el.evaluate(n => n.tagName === 'INPUT' && n.type === 'file');
if (!isFileInput) {
throw new Error('setInputFiles target must be input[type=file]');
}
const multiple = await el.evaluate(n => n.multiple);
if (!multiple && files.length > 1) {
throw new Error('input lacks multiple attribute; pass a single file');
}
await el.setInputFiles(files, { timeout: '30s' }); Type guard
async function isFileInput(el) {
if (!el) return false;
return await el.evaluate(n => n instanceof HTMLInputElement && n.type === 'file').catch(() => false);
} Try / catch
try {
await el.setInputFiles(files, { timeout: '30s' });
} catch (e) {
if (String(e).includes('not an input[type=file]')) {
const input = await page.waitForSelector('input[type="file"]');
await input.setInputFiles(files, { timeout: '30s' });
} else { throw e; }
} Prevention
- Always locate the hidden input[type=file] of upload widgets rather than the visible upload button.
- Check the multiple attribute before passing several files.
When it happens
Trigger: Calling el.setInputFiles(...) on an <input> that is not type=file; passing multiple files in the payload to an <input> without the multiple attribute; the file input being re-created by the framework and the handle going stale; timeout before the element is actionable.
Common situations: Drag-and-drop styled upload widgets that hide the real <input type=file> behind a button — developers select the visible button instead of the hidden input; React re-rendering the upload control after a failed upload, detaching the old handle.
Related errors
- parsing setInputFiles parameter
- selecting options
- checking hit target
- getting element position
- getting injected script
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/3b51f3789d759e41.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:1465
[]string{}, selectText, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
)
if _, err := call(h.ctx, selectTextAction, opts.Timeout); err != nil {
return fmt.Errorf("selecting text: %w", err)
}
applySlowMo(h.ctx)
return nil
}
// SetInputFiles sets the given files into the input file element.
func (h *ElementHandle) SetInputFiles(files *Files, opts *ElementHandleSetInputFilesOptions) error {
setInputFiles := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
return nil, handle.setInputFiles(apiCtx, files)
}
setInputFilesAction := h.newAction([]string{}, setInputFiles, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout)
if _, err := call(h.ctx, setInputFilesAction, opts.Timeout); err != nil {
return fmt.Errorf("setting input files: %w", err)
}
return nil
}
func (h *ElementHandle) setInputFiles(apiCtx context.Context, files *Files) error {
// allow clearing the input by passing an empty array
var payload []*File
if files != nil {
payload = files.Payload
}
fn := `
(node, injected, payload) => {
return injected.setInputFiles(node, payload);
}
`
evalOpts := evalOptions{
forceCallable: true,View on GitHub (pinned to 3fcf5388d7)