{"record":{"id":"a384878e96b10960","repo":"grafana/k6","slug":"waiting-for-selector-q-w","errorCode":null,"errorMessage":"waiting for selector %q: %w","messagePattern":"waiting for selector %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":1582,"sourceCode":"\n\treturn nil\n}\n\n// WaitForElementState waits for the element to reach the given state.\nfunc (h *ElementHandle) WaitForElementState(state string, opts *ElementHandleWaitForElementStateOptions) error {\n\t_, err := h.waitForElementState(h.ctx, []string{state}, opts.Timeout)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"waiting for element state %q: %w\", state, err)\n\t}\n\n\treturn nil\n}\n\n// WaitForSelector waits for the selector to appear in the DOM.\nfunc (h *ElementHandle) WaitForSelector(selector string, opts *FrameWaitForSelectorOptions) (*ElementHandle, error) {\n\thandle, err := h.waitForSelector(h.ctx, selector, opts)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"waiting for selector %q: %w\", selector, err)\n\t}\n\n\treturn handle, nil\n}\n\n// evalWithScript evaluates the given js code in the scope of this ElementHandle and returns the result.\n// The js code can call helper functions from injected_script.js.\nfunc (h *ElementHandle) evalWithScript(\n\tctx context.Context,\n\topts evalOptions, js string, args ...any,\n) (any, error) {\n\tscript, err := h.execCtx.getInjectedScript(h.ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting injected script: %w\", err)\n\t}\n\treturn h.eval(ctx, opts, js, append([]any{script}, args...)...)\n}\n","sourceCodeStart":1564,"sourceCodeEnd":1600,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/element_handle.go#L1564-L1600","documentation":"Wrapped failure from ElementHandle.WaitForSelector (elementHandle.waitForSelector(selector)). The inner path parses the selector (NewSelector — invalid syntax fails immediately), steps into frames when the selector contains iframe boundaries (>>), then waits for the target state. It fails on invalid selector syntax, on timeout waiting for the requested state, on strict-mode violations, or when the frame chain cannot be resolved.","triggerScenarios":"Malformed CSS/XPath/text selector that NewSelector rejects; selector never matching before opts.Timeout; state: 'visible' while the element exists but stays hidden; strict: true with multiple matches ('strict mode violation, multiple elements returned for selector query'); iframe part (>> iframe ...) of a chained selector not found, giving 'finding iframe with selector' failures.","commonSituations":"Selectors authored against one environment but the app renders differently in another; waiting inside an element handle scope where the sub-tree never gets the node; dynamic class names/IDs from CSS-in-JS; strict-by-default queries hitting duplicated DOM.","solutions":["Verify the selector matches in browser devtools against the exact page state, and prefer stable data-* attributes","Increase the timeout and pick the right state: el.waitForSelector(sel, { state: 'visible', timeout: '30s' })","For multiple matches, scope the selector more tightly or pass strict: false deliberately","For chained iframe selectors, confirm each frame segment matches an existing <iframe> element"],"exampleFix":"// before\nconst ok = page.$('#form').waitForSelector('div.row', { timeout: '1s' });\n\n// after\nconst ok = page.$('#form').waitForSelector('div.row[data-qa=row]', { state: 'visible', timeout: '30s' });","handlingStrategy":"validation","validationCode":"// fail fast on syntax and emptiness before waiting\nconst parsed = page.$(selector);\nif (parsed === null && strictModeWanted) {\n  // let waitForSelector drive the wait, but assert the selector is well-formed\n}\npage.waitForLoadState('domcontentloaded');","typeGuard":null,"tryCatchPattern":"try {\n  return el.waitForSelector(sel, { state: 'visible', timeout: '30s' });\n} catch (e) {\n  const msg = String(e);\n  if (msg.includes('strict mode violation')) {\n    return el.waitForSelector(sel, { strict: false, timeout: '30s' });\n  }\n  if (msg.includes('waiting for selector')) {\n    throw new Error(`selector ${sel} never matched: ${e}`);\n  }\n  throw e;\n}","preventionTips":["Verify selectors in devtools against the real page state","Prefer stable data-testid/data-qa attributes over generated classes","Set explicit state and timeout options instead of defaults"],"tags":["browser","selector","wait","iframe","strict-mode"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}