{"record":{"id":"a8ce45a4d6a5ce61","repo":"grafana/k6","slug":"frame-waitforfunction-w","errorCode":null,"errorMessage":"frame waitForFunction: %w","messagePattern":"frame waitForFunction: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/frame_mapping.go","lineNumber":436,"sourceCode":"\t\t\t}), nil\n\t\t},\n\t\t\"uncheck\": func(selector string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tpopts, err := parseFrameUncheckOptions(rt, opts, f.Timeout())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing frame uncheck options %q: %w\", selector, err)\n\t\t\t}\n\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn nil, f.Uncheck(selector, popts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"url\": f.URL,\n\t\t\"waitForFunction\": func(pageFunc, opts sobek.Value, args ...sobek.Value) (*sobek.Promise, error) {\n\t\t\tjs, popts, pargs, err := parseWaitForFunctionArgs(\n\t\t\t\trt, f.Timeout(), pageFunc, opts, args...,\n\t\t\t)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"frame waitForFunction: %w\", err)\n\t\t\t}\n\n\t\t\treturn promise(vu, func() (result any, reason error) {\n\t\t\t\treturn f.WaitForFunction(js, popts, pargs...) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"waitForLoadState\": func(state string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tpopts, err := parseFrameWaitForLoadStateOptions(rt, opts, f.Timeout())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing waitForLoadState %q options: %w\", state, err)\n\t\t\t}\n\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn nil, f.WaitForLoadState(state, popts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"waitForNavigation\": func(opts sobek.Value) (*sobek.Promise, error) {\n\t\t\treturn mapWaitForNavigation(rt, vu, f, opts)","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/grafana/k6/blob/8d06114777191d21ef885d05c5f8aa9e1ed838ae/internal/js/modules/k6/browser/browser/frame_mapping.go#L418-L454","documentation":"Thrown by the waitForFunction mapping (browser/frame_mapping.go:438) when parseWaitForFunctionArgs fails. The concrete failing branch is FrameWaitForFunctionOptions.Parse: 'wrong polling option value: %q; possible values: \"raf\", \"mutation\" or number'. k6 accepts only the strings 'raf' and 'mutation' or a numeric polling interval; Playwright's polling: 'interval' and numeric strings like '100' are rejected.","triggerScenarios":"frame.waitForFunction(() => window.ready, { polling: 'interval', interval: 100 }) (Playwright spelling); { polling: '100' } (interval as a string); explicitly passing polling: undefined/null as a present key (falls into the default reject branch).","commonSituations":"Porting Playwright examples verbatim; using the waitForFunction docs from Playwright instead of k6's; setting polling from environment/JSON config so the number arrives as a string.","solutions":["Use a number for interval polling: { polling: 100 }","Use the supported strings: { polling: 'raf' } or { polling: 'mutation' }","Delete the polling key entirely (defaults to 'raf')","Coerce config-sourced values: { polling: Number(cfg.interval) }"],"exampleFix":"// before\nframe.waitForFunction(() => window.ready, { polling: 'interval', interval: 100 });\n// after\nframe.waitForFunction(() => window.ready, { polling: 100 });","handlingStrategy":"validation","validationCode":"const POLLING = ['raf', 'mutation'];\nfunction normalizePolling(o = {}) {\n  const p = o.polling;\n  if (p === undefined) return o;\n  if (typeof p === 'number' && Number.isFinite(p) && p >= 0) return o;\n  if (POLLING.includes(p)) return o;\n  if (typeof p === 'string' && p.trim() !== '' && Number.isFinite(Number(p))) return { ...o, polling: Number(p) };\n  throw new Error(`invalid polling: ${p}; use 'raf', 'mutation' or a number`);\n}","typeGuard":"function isWaitForFunctionOptions(o) {\n  if (o == null) return true;\n  const p = o.polling;\n  return p === undefined || p === 'raf' || p === 'mutation' || (typeof p === 'number' && Number.isFinite(p));\n}","tryCatchPattern":"try { await frame.waitForFunction(fn, normalizePolling(opts)); } catch (e) { if (!String(e.message).includes('waitForFunction')) throw e; }","preventionTips":["Use k6's docs, not Playwright's, for waitForFunction polling","polling interval is a plain number in milliseconds: { polling: 100 }","Coerce polling from config with Number() before passing"],"tags":["k6","k6-browser","frame","wait-for-function","polling","options"],"backgroundTag":"invalid-enum-value","analyzedSha":"8d06114777191d21ef885d05c5f8aa9e1ed838ae","analyzedAt":"2026-09-14T20:10:14.619Z","contentChangedAt":"2026-09-14T20:10:14.619Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}