{"record":{"id":"895a74c6bb0149b7","repo":"grafana/k6","slug":"querying-all-selector-q-w","errorCode":null,"errorMessage":"querying all selector %q: %w","messagePattern":"querying all selector %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":1254,"sourceCode":"\tif element == nil {\n\t\tdefer func() {\n\t\t\tif err := handle.Dispose(); err != nil {\n\t\t\t\terr = fmt.Errorf(\"disposing element handle: %w\", err)\n\t\t\t\trerr = errors.Join(err, rerr)\n\t\t\t}\n\t\t}()\n\t\treturn nil, fmt.Errorf(\"querying selector %q\", selector)\n\t}\n\n\treturn element, nil\n}\n\n// QueryAll queries element subtree for matching elements.\n// If no element matches the selector, the return value resolves to \"null\".\nfunc (h *ElementHandle) QueryAll(selector string) ([]*ElementHandle, error) {\n\thandles, err := h.queryAll(selector, h.evalWithScript)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"querying all selector %q: %w\", selector, err)\n\t}\n\n\treturn handles, nil\n}\n\nfunc (h *ElementHandle) queryAll(selector string, eval evalFunc) (_ []*ElementHandle, rerr error) {\n\tparsedSelector, err := NewSelector(selector)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing selector %q: %w\", selector, err)\n\t}\n\tresult, err := eval(\n\t\th.ctx,\n\t\tevalOptions{forceCallable: true, returnByValue: false},\n\t\tjs.QueryAll,\n\t\tparsedSelector,\n\t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"querying all selectors %q: %w\", selector, err)","sourceCodeStart":1236,"sourceCodeEnd":1272,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/element_handle.go#L1236-L1272","documentation":"ElementHandle.QueryAll() ($$) wraps every failure of its internal queryAll with 'querying all selector' (element_handle.go:1254). The wrapped message tells the real story — almost always either 'parsing selector' (bad selector string) or 'querying all selectors' (evaluation/context failure).","triggerScenarios":"$$() with an empty/invalid selector or duplicate '*' captures; evaluating the injected js.QueryAll script while the context is destroyed by navigation or the target closes.","commonSituations":"Bulk-scraping loops (collecting all rows/links) that run across SPA navigations or at iteration teardown; dynamic selectors that can be blank.","solutions":["Read the wrapped message: parsing -> fix the selector (see 'parsing selector'); evaluation -> fix the timing (see 'querying all selectors')","Wait for a stable load state before bulk queries","Validate dynamically built selectors are non-empty before calling $$","Retry once on transient navigation races"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate before $$\nif (!sel || sel.trim() === '') throw new Error('empty selector');\nawait page.waitForLoadState('domcontentloaded');","typeGuard":null,"tryCatchPattern":"try { const all = await el.$$(sel); }\ncatch (e) {\n  if (/parsing selector/.test(e.message)) throw new Error(`bad selector: ${sel}`);\n  if (/querying all selectors/.test(e.message)) { await page.waitForLoadState(); return await el.$$(sel); }\n  throw e;\n}","preventionTips":["Branch on the wrapped message: parse errors vs evaluation races","Validate dynamic selectors non-empty","Wait for stable state before bulk scrapes"],"tags":["selector","browser","evaluation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}