{"record":{"id":"1e44d0a059147547","repo":"grafana/k6","slug":"counting-elements-w","errorCode":null,"errorMessage":"counting elements: %w","messagePattern":"counting elements: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/frame.go","lineNumber":641,"sourceCode":"\t)\n\tif _, err := call(f.ctx, act, opts.Timeout); err != nil {\n\t\treturn errorFromDOMError(err)\n\t}\n\n\treturn nil\n}\n\nfunc (f *Frame) count(selector string) (int, error) {\n\tf.log.Debugf(\"Frame:count\", \"fid:%s furl:%q sel:%q\", f.ID(), f.URL(), selector)\n\n\tdocument, err := f.document()\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"getting document: %w\", err)\n\t}\n\n\tc, err := document.count(f.ctx, selector)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"counting elements: %w\", err)\n\t}\n\n\treturn c, nil\n}\n\n// Check clicks the first element found that matches selector.\nfunc (f *Frame) Check(selector string, popts *FrameCheckOptions) error {\n\tf.log.Debugf(\"Frame:Check\", \"fid:%s furl:%q sel:%q\", f.ID(), f.URL(), selector)\n\n\tif err := f.check(selector, popts); err != nil {\n\t\treturn fmt.Errorf(\"checking %q: %w\", selector, err)\n\t}\n\n\tapplySlowMo(f.ctx)\n\n\treturn nil\n}\n","sourceCodeStart":623,"sourceCodeEnd":659,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/frame.go#L623-L659","documentation":"After the document handle is obtained, Frame.count() calls document.count(ctx, selector), which evaluates document.querySelectorAll(selector).length in the main world. This error wraps a failure of that evaluation — an invalid selector, a CDP error, or the execution context dying mid-evaluation.","triggerScenarios":"Malformed CSS selector (unbalanced brackets, stray parens) raises a DOMException in the page; the frame navigates between getting the document and evaluating count; the CDP session/target is closed (browser crashed or page closed).","commonSituations":"Dynamically-built selector strings (typos, missing quotes) passed to count(); counting during redirects; test continuing after the browser/page was closed by another branch; cross-origin iframes with a stale context.","solutions":["Validate the selector: try it in browser DevTools document.querySelectorAll('<sel>') or validate it before use.","Wait for load state and retry once — transient context destruction during navigation resolves itself.","Verify the page/browser is still open before calling (check earlier errors in the iteration)."],"exampleFix":"// before\nconst n = frame.count(`a[href=${dynamic}]`); // unquoted attr -> invalid selector\n\n// after\nconst sel = `a[href=\"${dynamic}\"]`;\nconst n = frame.count(sel);","handlingStrategy":"try-catch","validationCode":"const validSelector = (s) => { try { document.querySelectorAll(s); return true; } catch { return false; } }; // in-page via evaluate:\nawait frame.evaluate('(s) => { try { document.createDocumentFragment().querySelector(s); return true; } catch { return false; } }', sel);","typeGuard":null,"tryCatchPattern":"try {\n  const n = frame.count(sel);\n} catch (e) {\n  console.warn(`count failed for ${sel}:`, e.message);\n}","preventionTips":["Build selectors from constants, not string concatenation of raw input.","Validate dynamic selectors once in DevTools before scripting them.","Check the page is still open before querying after close-prone branches."],"tags":["browser","count","invalid-selector","execution-context","cdp"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}