{"record":{"id":"34354da6793a11c8","repo":"grafana/k6","slug":"getting-frame-title-w","errorCode":null,"errorMessage":"getting frame title: %w","messagePattern":"getting frame title: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/frame.go","lineNumber":1898,"sourceCode":"\t}\n\n\treturn s, true, nil\n}\n\n// Timeout will return the default timeout or the one set by the user.\n// It's an internal method not to be exposed as a JS API.\nfunc (f *Frame) Timeout() time.Duration {\n\treturn f.defaultTimeout()\n}\n\n// Title returns the title of the frame.\nfunc (f *Frame) Title() (string, error) {\n\tf.log.Debugf(\"Frame:Title\", \"fid:%s furl:%q\", f.ID(), f.URL())\n\n\tjs := `() => document.title`\n\tv, err := f.Evaluate(js)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"getting frame title: %w\", err)\n\t}\n\ts, ok := v.(string)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"getting frame title: expected string, got %T\", v)\n\t}\n\n\treturn s, nil\n}\n\n// Type text on the first element found matches the selector.\nfunc (f *Frame) Type(selector, text string, popts *FrameTypeOptions) error {\n\tf.log.Debugf(\"Frame:Type\", \"fid:%s furl:%q sel:%q text:%q\", f.ID(), f.URL(), selector, text)\n\n\tif err := f.typ(selector, text, popts); err != nil {\n\t\treturn fmt.Errorf(\"typing %q in %q: %w\", text, selector, err)\n\t}\n\n\tapplySlowMo(f.ctx)","sourceCodeStart":1880,"sourceCodeEnd":1916,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/js/modules/k6/browser/common/frame.go#L1880-L1916","documentation":"Thrown by k6 browser's frame.Title(): it evaluates `() => document.title` in the frame, and the evaluation itself failed. That means the frame's execution context was unavailable or destroyed — navigation in flight, frame detached, or page closed.","triggerScenarios":"frame.title()/page.title() called during navigation (old context destroyed, new one not ready), on a detached frame (iframe removed from DOM), or after the page/target was closed.","commonSituations":"Asserting the title immediately after page.goto() before commit; reading titles of transient iframes that get removed; iterating page.frames() while the page mutates.","solutions":["Wait for the page to settle: page.waitForLoadState('domcontentloaded') before title()","Use waitForNavigation around actions that navigate, then read the title","Skip stale frames: check frame.isDetached() if available, or re-list page.frames()","Guard with page.isClosed() in teardown paths"],"exampleFix":"// before\nconst t = page.title();\n\n// after\npage.waitForLoadState('domcontentloaded');\nconst t = page.title();","handlingStrategy":"try-catch","validationCode":"page.waitForLoadState('domcontentloaded');\nif (page.isClosed()) throw new Error('page closed; cannot read title');","typeGuard":"const isTitle = (v) => typeof v === 'string';","tryCatchPattern":"let title = '';\ntry {\n  title = page.title();\n} catch (e) {\n  console.log(`title read raced navigation: ${e}`);\n  page.waitForLoadState('domcontentloaded');\n  title = page.title();\n}","preventionTips":["Read the title only after the navigation settles (waitForNavigation/waitForLoadState)","Don't hold frame references across navigations"],"tags":["k6","browser","title","frame","navigation"],"backgroundTag":"frame-detached","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"}