microsoft/playwright · error · Error

Unable to adopt element handle from a different document

Error message

Unable to adopt element handle from a different document

What it means

adoptElementHandle() calls DOM.resolveNode with the source handle's objectId and the destination context id; if the engine cannot resolve the node in the target context (subtype 'null') it throws dom.kUnableToAdoptErrorMessage. This happens when the handle belongs to a different document than the destination frame's context (e.g. across iframes/processes where the node isn't reachable).

Source

Thrown at packages/playwright-core/src/server/webkit/wkPage.ts:1005

  async setInputFilePaths(progress: Progress, handle: dom.ElementHandle<HTMLInputElement>, paths: string[]): Promise<void> {
    const pageProxyId = this._pageProxySession.sessionId;
    const objectId = handle._objectId;
    if (this._browserContext._browser?.options.channel === 'webkit-wsl')
      paths = await progress.race(Promise.all(paths.map(path => translatePathToWSL(path))));
    await progress.race(Promise.all([
      this._pageProxySession.connection.browserSession.send('Playwright.grantFileReadAccess', { pageProxyId, paths }),
      this._session.send('DOM.setInputFiles', { objectId, paths })
    ]));
  }

  async adoptElementHandle<T extends Node>(handle: dom.ElementHandle<T>, to: dom.FrameExecutionContext): Promise<dom.ElementHandle<T>> {
    const result = await this._session.sendMayFail('DOM.resolveNode', {
      objectId: handle._objectId,
      executionContextId: (to.delegate as WKExecutionContext)._contextId
    });
    if (!result || result.object.subtype === 'null')
      throw new Error(dom.kUnableToAdoptErrorMessage);
    return createHandle(to, result.object) as dom.ElementHandle<T>;
  }

  async inputActionEpilogue(): Promise<void> {
  }

  async resetForReuse(progress: Progress): Promise<void> {
  }

  async getFrameElement(frame: frames.Frame): Promise<dom.ElementHandle> {
    const parent = frame.parentFrame();
    if (!parent)
      throw new Error('Frame has been detached.');
    const context = await parent.mainContext();
    const result = await this._session.send('DOM.resolveNode', {
      frameId: frame._id,
      executionContextId: (context.delegate as WKExecutionContext)._contextId
    });

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Re-query the element inside the destination frame rather than adopting a foreign handle (use a selector/locator scoped to the target frame).
  2. Verify the handle's frame is the same document as the destination context before adopting; refresh stale handles.
  3. For cross-origin iframes, run logic inside the owning frame and pass serializable data out, not the handle.

Example fix

// before
const h = await parentFrame.$('#node');
await childFrame.evaluate(n => n.remove(), h); // adoption fails across docs

// after
await childFrame.$$eval('#node', els => els.forEach(e => e.remove()));
Defensive patterns

Strategy: validation

Validate before calling

function sameDocument(handle, destFrame) {
  return handle?.frame === destFrame;
}
if (sameDocument(handle, frame)) await frame.evaluate(h => h.remove(), handle);
else await frame.$$eval(sel, els => els.forEach(e => e.remove()));

Type guard

null

Try / catch

try { await destFrame.evaluate(fn, foreignHandle); }
catch (e) {
  if (/different document/.test(e.message)) await destFrame.$$eval(sel, els => els.forEach(e => e.remove()));
  else throw e;
}

Prevention

When it happens

Trigger: Adopting an ElementHandle originating in document A into a context belonging to document B — cross-origin iframe handles, handles from a detached/navigated document, or handles whose underlying node was removed before adoption resolved.

Common situations: Passing element handles from one frame into evaluateHandle of another (cross-origin). Reusing a handle after its frame navigated. Cross-process iframe workflows on WebKit where the node is not directly resolvable.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/f1bc5ad749396e49. Report an issue: GitHub.