{"record":{"id":"979f5ca587e6844e","repo":"grafana/k6","slug":"element-is-not-an-iframe","errorCode":null,"errorMessage":"element is not an iframe","messagePattern":"element is not an iframe","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":862,"sourceCode":"\t\treturn fmt.Errorf(\"clicking on element: %w\", err)\n\t}\n\tapplySlowMo(h.ctx)\n\n\treturn nil\n}\n\n// ContentFrame returns the frame that contains this element.\nfunc (h *ElementHandle) ContentFrame() (*Frame, error) {\n\tvar (\n\t\tnode *cdp.Node\n\t\terr  error\n\t)\n\taction := dom.DescribeNode().WithObjectID(h.remoteObject.ObjectID)\n\tif node, err = action.Do(cdp.WithExecutor(h.ctx, h.session)); err != nil {\n\t\treturn nil, fmt.Errorf(\"getting remote node %q: %w\", h.remoteObject.ObjectID, err)\n\t}\n\tif node == nil || node.FrameID == \"\" {\n\t\treturn nil, fmt.Errorf(\"element is not an iframe\")\n\t}\n\n\tframe, ok := h.frame.manager.getFrameByID(node.FrameID)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"frame not found for id %s\", node.FrameID)\n\t}\n\n\treturn frame, nil\n}\n\n// Dblclick scrolls element into view and double clicks on the element.\nfunc (h *ElementHandle) Dblclick(opts *ElementHandleDblclickOptions) error {\n\tdblclick := func(_ context.Context, handle *ElementHandle, p *Position) (any, error) {\n\t\treturn nil, handle.dblclick(p, opts.ToMouseClickOptions())\n\t}\n\tdblclickAction := h.newPointerAction(dblclick, &opts.ElementHandleBasePointerOptions)\n\tif _, err := call(h.ctx, dblclickAction, opts.Timeout); err != nil {\n\t\treturn fmt.Errorf(\"double clicking on element: %w\", err)","sourceCodeStart":844,"sourceCodeEnd":880,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/element_handle.go#L844-L880","documentation":"ContentFrame() returns this when DOM.describeNode yields a node with no FrameID: the described node is not an iframe element. Only iframe elements own a content frame, so asking a regular element for one is a usage error.","triggerScenarios":"handle.contentFrame() on a div/button/any non-iframe element; also frame-crossing selectors whose 'before frame' part resolves to a non-iframe node (then surfaced via 'getting iframe frame').","commonSituations":"Selector matches a wrapper div instead of the iframe; assuming an embedded player/widget is an iframe when it is a div/video; typos in the iframe selector.","solutions":["Verify the element's tag is IFRAME before calling contentFrame()","Tighten the selector to target the <iframe> itself","Use page.frameLocator(selector) which encodes the intent explicitly"],"exampleFix":"// before\nconst frame = await (await page.$('#player')).contentFrame(); // element is not an iframe\n\n// after\nconst frame = await (await page.$('#player iframe')).contentFrame();\n// or\nconst fl = page.frameLocator('#player iframe');","handlingStrategy":"type-guard","validationCode":"const isIframe = await handle.evaluate((el) => el.tagName === 'IFRAME');\nif (!isIframe) throw new Error('contentFrame requires an <iframe> element');","typeGuard":"async function isFrameElement(handle) {\n  return handle.evaluate((el) => el instanceof HTMLIFrameElement);\n}","tryCatchPattern":"try {\n  const frame = await handle.contentFrame();\n} catch (e) {\n  if (String(e).includes('element is not an iframe')) {\n    // selector matched the wrong node; re-target the <iframe> itself\n  } else { throw e; }\n}","preventionTips":["Point selectors at the iframe element, not its wrapper","Use frameLocator() to express frame intent explicitly"],"tags":["browser","iframe","usage-error","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}