{"record":{"id":"723f7b2cc6bff4ba","repo":"grafana/k6","slug":"getting-browser-version-information-w","errorCode":null,"errorMessage":"getting browser version information: %w","messagePattern":"getting browser version information: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/js/modules/k6/browser/common/browser.go","lineNumber":807,"sourceCode":"\tproduct := b.version.product\n\t_, after, ok := strings.Cut(product, \"/\")\n\tif !ok {\n\t\treturn product\n\t}\n\treturn after\n}\n\n// fetchVersion returns the browser version information.\nfunc (b *Browser) fetchVersion() (browserVersion, error) {\n\tvar (\n\t\tbv  browserVersion\n\t\terr error\n\t)\n\tbv.protocolVersion, bv.product, bv.revision, bv.userAgent, bv.jsVersion, err = cdpbrowser.\n\t\tGetVersion().\n\t\tDo(cdp.WithExecutor(b.vuCtx, b.conn))\n\tif err != nil {\n\t\treturn browserVersion{}, fmt.Errorf(\"getting browser version information: %w\", err)\n\t}\n\n\t// Adjust the user agent to remove the headless part.\n\t//\n\t// Including Headless might cause issues with some websites that treat headless\n\t// browsers differently. Later on, [BrowserContext] will set the user agent to\n\t// this user agent if not set by the user. This will force [FrameSession] to\n\t// set the user agent to the browser's user agent.\n\t//\n\t// Doing this here provides a consistent user agent across all browser contexts.\n\t// Also, it makes it consistent to query the user agent from the browser.\n\tif b.browserOpts.Headless {\n\t\tbv.userAgent = strings.ReplaceAll(bv.userAgent, \"Headless\", \"\")\n\t}\n\n\treturn bv, nil\n}\n","sourceCodeStart":789,"sourceCodeEnd":825,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/js/modules/k6/browser/common/browser.go#L789-L825","documentation":"fetchVersion calls Browser.getVersion over CDP right after connecting to fill protocol/product/user-agent info (used by Version()/UserAgent()). This error wraps that call failing, meaning the connection died immediately after the handshake or the endpoint is not behaving like a Chromium browser-level DevTools endpoint.","triggerScenarios":"The WS URL pointing at a page-level endpoint (/devtools/page/<id>) or non-browser service; a stale ws URL from a previous browser session; the browser process crashing or the proxy dropping the session right after connect.","commonSituations":"K6_BROWSER_WS_URL copied from an old run or pointing at Chrome's HTTP port instead of the webSocketDebuggerUrl; browserless/CDP proxies terminating sessions; protocol version mismatch with unusual Chromium builds.","solutions":["Fetch http://host:port/json/version and use its webSocketDebuggerUrl verbatim — old session URLs are invalid","Confirm the browser process stays alive across the connect (check logs/exit code)","Verify the endpoint is a Chromium browser-level DevTools endpoint, not a page target or WebDriver endpoint","Match the Chromium/headless-shell version to what the k6 browser module supports"],"exampleFix":"# before\nK6_BROWSER_WS_URL=ws://localhost:9222/devtools/page/abc123 k6 run s.js # page-level endpoint\n\n# after\ncurl -s http://localhost:9222/json/version | jq -r .webSocketDebuggerUrl\nK6_BROWSER_WS_URL=<browser-level url> k6 run s.js","handlingStrategy":"validation","validationCode":"// Preflight the remote DevTools endpoint and pin the fresh browser-level URL\nconst res = http.get(`${__ENV.K6_BROWSER_CDP}/json/version`);\nif (res.status !== 200) throw new Error('CDP endpoint not serving /json/version');\nconst wsUrl = res.json('webSocketDebuggerUrl');\nif (!wsUrl || !wsUrl.includes('/devtools/browser/'))\n  throw new Error('webSocketDebuggerUrl is not a browser-level endpoint');\n__ENV.K6_BROWSER_WS_URL = wsUrl;","typeGuard":null,"tryCatchPattern":"try {\n  browser.userAgent(); // triggers version fetch\n} catch (e) {\n  if (String(e).includes('getting browser version information')) {\n    // refetch /json/version, relaunch with fresh URL, retry once\n  }\n}","preventionTips":["Never hardcode WS URLs across runs; always resolve them via /json/version","Use browser-level (/devtools/browser/...) endpoints only","Health-check remote browsers before the run"],"tags":["cdp","browser","version","connection","remote-debugging"],"backgroundTag":"cdp-protocol-error","analyzedSha":"3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}