{"record":{"id":"825678860f713048","repo":"microsoft/playwright","slug":"jshandle-is-not-a-dom-node-handle","errorCode":null,"errorMessage":"JSHandle is not a DOM node handle","messagePattern":"JSHandle is not a DOM node handle","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/bidi/bidiExecutionContext.ts","lineNumber":167,"sourceCode":"  }\n\n  async remoteObjectForNodeId(context: dom.FrameExecutionContext, nodeId: bidi.Script.SharedReference): Promise<dom.ElementHandle> {\n    const result = await this._remoteValueForReference(nodeId, true);\n    if (!('handle' in result))\n      throw new Error('Can\\'t get remote object for nodeId');\n    return createHandle(context, result) as dom.ElementHandle;\n  }\n\n  async contentFrameIdForFrame(handle: dom.ElementHandle) {\n    const contentWindow = await this._rawCallFunction('e => e.contentWindow', [{ handle: handle._objectId }]);\n    if (contentWindow?.type === 'window')\n      return contentWindow.value.context;\n    return null;\n  }\n\n  async frameIdForWindowHandle(handle: js.JSHandle): Promise<string | null> {\n    if (!handle._objectId)\n      throw new Error('JSHandle is not a DOM node handle');\n    const contentWindow = await this._remoteValueForReference({ handle: handle._objectId });\n    if (contentWindow.type === 'window')\n      return contentWindow.value.context;\n    return null;\n  }\n\n  private async _remoteValueForReference(reference: bidi.Script.RemoteReference, createHandle?: boolean) {\n    return await this._rawCallFunction('e => e', [reference], createHandle);\n  }\n\n  private async _rawCallFunction(functionDeclaration: string, args: bidi.Script.LocalValue[], createHandle?: boolean, awaitPromise = true): Promise<bidi.Script.RemoteValue> {\n    const response = await this._session.send('script.callFunction', {\n      functionDeclaration,\n      target: this._target,\n      arguments: args,\n      // \"Root\" is necessary for the handle to be returned.\n      resultOwnership: createHandle ? bidi.Script.ResultOwnership.Root : bidi.Script.ResultOwnership.None,\n      serializationOptions: { maxObjectDepth: 0, maxDomDepth: 0 },","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/bidi/bidiExecutionContext.ts#L149-L185","documentation":"Thrown by the WebDriver BiDi execution context when an internal operation needs a remote object reference from a JSHandle, but the handle's `_objectId` is falsy. A primitive JSHandle (string, number, boolean, undefined, null) has no backing remote object in BiDi, so it cannot be used where a node/window handle reference is required.","triggerScenarios":"Internal call to `frameIdForWindowHandle(handle)` in bidiExecutionContext.ts:167 where `handle._objectId` is undefined. Reached when BiDi frame/window introspection is given a handle produced by `page.evaluateHandle(() => somePrimitive)` instead of an object/window.","commonSituations":"Rare for end users. Surfaces in Firefox-over-BiDi when a primitive-valued JSHandle leaks into frame-resolution logic, or when internal helpers are reused with handles of the wrong shape. Usually indicates a Playwright internal bug rather than a user mistake.","solutions":["Obtain handles from expressions that return objects/windows, e.g. `page.evaluateHandle(() => window)`, not primitives","If you hit this through a public API, file a Playwright issue with a repro — it typically signals an internal invariant violation","Avoid passing arbitrary `evaluateHandle` results into frame/element APIs; re-query the element with a Locator"],"exampleFix":"// before\nconst h = await page.evaluateHandle(() => 'foo');\n// ... passed into frame logic\n\n// after\nconst h = await page.evaluateHandle(() => window);\n// or re-query the node directly\nconst loc = page.locator('iframe');","handlingStrategy":"try-catch","validationCode":"// _objectId is internal; guard at the public boundary by ensuring\n// the handle comes from an object-returning expression.\nconst h = await page.evaluateHandle(() => window);\n// Re-query nodes via Locators rather than reusing arbitrary handles.","typeGuard":"// No public _objectId; approximate by checking the handle is non-primitive.\nfunction isObjectHandle(h: JSHandle): boolean {\n  // Primitives report these types; objects/nodes report 'object'/'function'/'node'.\n  const t = (h as any)._objectType ?? 'object';\n  return t === 'object' || t === 'function' || t === 'node';\n}","tryCatchPattern":"try {\n  // operation that needs a node/window handle\n} catch (e) {\n  if (e instanceof Error && /not a DOM node handle/.test(e.message)) {\n    // re-acquire a valid handle or rethrow with context\n  }\n  throw e;\n}","preventionTips":["Prefer Locators over manually managed ElementHandles/JSHandles","Obtain handles from object/window-returning expressions, not primitives","Treat this error as an internal-invariant violation and report it upstream"],"tags":["bidi","firefox","jshandle","internal"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}