{"record":{"id":"cd6b72841bb07558","repo":"grafana/k6","slug":"waiting-for-q-w","errorCode":null,"errorMessage":"waiting for %q: %w","messagePattern":"waiting for %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/locator.go","lineNumber":653,"sourceCode":"\n\topts.Strict = true\n\tif err := l.frame.dispatchEvent(l.selector, typ, eventInit, opts); err != nil {\n\t\treturn fmt.Errorf(\"dispatching locator event %q to %q: %w\", typ, l.selector, err)\n\t}\n\n\tapplySlowMo(l.ctx)\n\n\treturn nil\n}\n\n// WaitFor waits for the element matching the locator's selector with strict mode on.\nfunc (l *Locator) WaitFor(opts *FrameWaitForSelectorOptions) error {\n\tl.log.Debugf(\"Locator:WaitFor\", \"fid:%s furl:%q sel:%q opts:%+v\", l.frame.ID(), l.frame.URL(), l.selector, opts)\n\n\topts.Strict = true\n\t_, err := l.frame.waitFor(l.selector, opts, 20)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"waiting for %q: %w\", l.selector, err)\n\t}\n\n\treturn nil\n}\n\n// DefaultTimeout returns the default timeout for the locator.\n// This is an internal API and should not be used by users.\nfunc (l *Locator) DefaultTimeout() time.Duration {\n\treturn l.frame.defaultTimeout()\n}\n\n// FrameLocator represent a way to find element(s) in an iframe.\ntype FrameLocator struct {\n\tselector string\n\n\tframe *Frame\n\n\tctx context.Context","sourceCodeStart":635,"sourceCodeEnd":671,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/locator.go#L635-L671","documentation":"Thrown by Locator.WaitFor() when the wrapped frame.waitFor call fails after up to 20 internal retry rounds. Strict mode is forced on, so the selector must resolve to exactly one element. The dominant cause is a timeout: the element never reaches the requested state (attached/visible/hidden) before opts.Timeout expires; multiple matches also fail with a strict-mode violation.","triggerScenarios":"locator.waitFor({state, timeout}) where exactly one element never appears/visibilize before the timeout; selector matches multiple elements (strict mode violation); waiting for state:'hidden' on an element that never disappears.","commonSituations":"Waiting for late SPA content with the default 30s timeout on slow or overloaded environments; selectors that match multiple nodes; asserting disappearance (state:'hidden') of elements that persist; wrong selector after a re-render.","solutions":["Verify the selector manually (devtools) and make it match exactly one element","Increase opts.timeout to cover slow CI/load-test environments","Choose the right state: 'attached' for existence, 'visible' for rendered, 'hidden' for disappearance","If the element only exists after an action, put waitFor after that action, not before"],"exampleFix":"// before\nawait page.locator('.results-row').waitFor(); // default timeout too short in CI\n\n// after\nawait page.locator('.results-row').waitFor({ state: 'visible', timeout: '60s' });","handlingStrategy":"try-catch","validationCode":"// fail fast with a clearer message than the default timeout wrap\nconst count = await page.locator(sel).count();\nif (count > 1) throw new Error(`strict mode: ${sel} matches ${count} elements`);\nawait page.locator(sel).waitFor({ state: 'visible', timeout: '60s' });","typeGuard":"async function isSingleMatch(page, sel) {\n  const n = await page.locator(sel).count();\n  return n === 1;\n}","tryCatchPattern":"try {\n  await page.locator(sel).waitFor({ timeout: '60s' });\n} catch (e) {\n  if (/timeout/i.test(e.message)) {\n    throw new Error(`element never appeared: ${sel} (page url: ${page.url()})`);\n  }\n  throw e;\n}","preventionTips":["Pick state ('attached'|'visible'|'hidden') deliberately for each wait","Scale timeouts with environment slowness (CI > local)","Verify selectors in devtools against the rendered DOM, not the source"],"tags":["browser","locator","timeout","wait","strict-mode"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}