{"record":{"id":"ef7d68107ba04bd1","repo":"grafana/k6","slug":"can-t-fetch-the-page-for-unknown-reason","errorCode":null,"errorMessage":"can't fetch the page for unknown reason","messagePattern":"can't fetch the page for unknown reason","errorType":"exception","errorClass":"UserFriendlyError","httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/browser.go","lineNumber":559,"sourceCode":"\tcase <-waitForPage:\n\t\tb.logger.Debugf(\"Browser:newPageInContext:<-waitForPage\", \"tid:%v bctxid:%v\", tid, id)\n\t\tb.pagesMu.RLock()\n\t\tpage = b.pages[tid]\n\t\tb.pagesMu.RUnlock()\n\tcase <-ctx.Done():\n\t\tb.logger.Debugf(\"Browser:newPageInContext:<-ctx.Done\", \"tid:%v bctxid:%v err:%v\", tid, id, ContextErr(ctx))\n\t}\n\n\tif err = ContextErr(ctx); err != nil {\n\t\terr = &k6ext.UserFriendlyError{\n\t\t\tErr:     err,\n\t\t\tTimeout: b.browserOpts.Timeout,\n\t\t}\n\t}\n\n\tif err == nil && page == nil {\n\t\terr = &k6ext.UserFriendlyError{\n\t\t\tErr: errors.New(\"can't fetch the page for unknown reason\"),\n\t\t}\n\t}\n\n\treturn page, err\n}\n\n// Close shuts down the browser.\nfunc (b *Browser) Close() {\n\tif !b.closing.CompareAndSwap(false, true) {\n\t\tb.logger.Warnf(\n\t\t\t\"Browser:Close\",\n\t\t\t\"Please call browser.close only once, and do not use the browser after calling close.\",\n\t\t)\n\t\treturn\n\t}\n\t// This will help with some cleanup in the connection and event loop above in\n\t// initEvents().\n\tdefer b.browserCancelFn(errors.New(\"browser closed\"))","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/js/modules/k6/browser/common/browser.go#L541-L577","documentation":"Browser.newPageInContext treats 'no page AND no error' after Target.createTarget as an impossible outcome and converts it into a wrapped UserFriendlyError with this message (internal/js/modules/k6/browser/common/browser.go:564). It fires when the CDP call neither failed nor produced a usable page before the context finished — typically the target was destroyed immediately, the browser died, or a timeout raced page creation.","triggerScenarios":"browser.newPage() racing browser/context close; a remote wsURL browser crashing or being OOM-killed mid-call; a low browser timeout (K6_BROWSER_TIMEOUT / timeout option) expiring exactly during page creation; Chromium killing the target on startup (bad flags, corrupt data dir).","commonSituations":"Containerized/remote Chrome under memory pressure restarting between calls; scenarios launching many pages concurrently; flaky CI where the browser container is still starting; leftover chrome processes locking the user-data dir.","solutions":["Retry the page creation once with a short backoff — this is frequently a transient race","Raise the browser timeout: K6_BROWSER_TIMEOUT=60s (or the timeout browser option)","Check the remote browser's health and logs (container restarts, OOM kills) and give it more memory/CPU","Ensure nothing closes the browser/context concurrently with newPage()","Upgrade k6 — page-creation and timeout paths have been hardened across releases"],"exampleFix":"// before\nconst page = await browser.newPage();\n\n// after\nasync function newPageWithRetry(browser, tries = 2) {\n  for (let i = 0; ; i++) {\n    try { return await browser.newPage(); }\n    catch (e) {\n      if (i >= tries || !/unknown reason/.test(e.message)) throw e;\n      await new Promise((r) => setTimeout(r, 500));\n    }\n  }\n}\nconst page = await newPageWithRetry(browser);","handlingStrategy":"retry","validationCode":"// cheap pre-flight for a remote browser before creating pages\nimport http from 'k6/http';\nconst checkBrowserUp = (endpoint) => http.get(`http://${endpoint}/json/version`).status === 200;","typeGuard":null,"tryCatchPattern":"async function newPageWithRetry(browser, tries = 2, delayMs = 500) {\n  for (let i = 0; ; i++) {\n    try {\n      return await browser.newPage();\n    } catch (e) {\n      if (i >= tries || !/unknown reason/.test(String(e?.message || e))) throw e;\n      await new Promise((r) => setTimeout(r, delayMs));\n    }\n  }\n}","preventionTips":["Set a generous browser timeout (K6_BROWSER_TIMEOUT or the timeout option) instead of defaults under load","Healthcheck remote browsers (/json/version) before the run and watch for container OOM restarts","Serialize page creation; avoid launching many pages concurrently against one browser","Keep k6 current — page-creation and timeout handling improve release over release"],"tags":["browser","page-creation","cdp","race-condition","timeout","remote-browser"],"backgroundTag":"page-creation-failed","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"}