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` re-throws a generic message when BiDi's `remoteObjectForNodeId` fails to re-parent a node into a different frame's execution context. Cross-document node adoption is limited under BiDi; the catch hides the underlying BiDi error behind `kUnableToAdoptErrorMessage`.
Source
Thrown at packages/playwright-core/src/server/bidi/bidiPage.ts:698
}
async setInputFilePaths(progress: Progress, handle: dom.ElementHandle<HTMLInputElement>, paths: string[]): Promise<void> {
const fromContext = toBidiExecutionContext(handle._context);
await progress.race(this._session.send('input.setFiles', {
context: this._session.sessionId,
element: await progress.race(fromContext.nodeIdForElementHandle(handle)),
files: paths,
}));
}
async adoptElementHandle<T extends Node>(handle: dom.ElementHandle<T>, to: dom.FrameExecutionContext): Promise<dom.ElementHandle<T>> {
const fromContext = toBidiExecutionContext(handle._context);
const nodeId = await fromContext.nodeIdForElementHandle(handle);
const executionContext = toBidiExecutionContext(to);
try {
return await executionContext.remoteObjectForNodeId(to, nodeId) as dom.ElementHandle<T>;
} catch {
throw new Error(dom.kUnableToAdoptErrorMessage);
}
}
async inputActionEpilogue(): Promise<void> {
}
async resetForReuse(progress: Progress): Promise<void> {
// See https://github.com/microsoft/playwright/issues/22432.
await this.rawMouse.move(progress, 0, 0, 'none', new Set(), new Set(), false);
}
async pdf(options: channels.PagePdfParams): Promise<Buffer> {
return this._pdf.generate(options);
}
async getFrameElement(frame: frames.Frame): Promise<dom.ElementHandle> {
const parent = frame.parentFrame();
if (!parent)View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Re-query the element in the target frame instead of adopting across frames
- Use Locators scoped to the correct frame
- Avoid passing ElementHandles across cross-origin frame boundaries
Example fix
// before
const handle = await frame1.locator('button').elementHandle();
await frame2.evaluate(h => h.click(), handle); // cross-frame adoption
// after
await frame2.locator('button').click(); // re-query in target frame Defensive patterns
Strategy: try-catch
Validate before calling
// Prefer re-querying elements in the target frame rather than adopting handles.
// If you must pass a handle, verify same-origin first:
function sameOrigin(a: URL, b: URL): boolean {
return a.origin === b.origin;
} Try / catch
try {
await targetFrame.evaluate(fn, handleFromOtherFrame);
} catch (e) {
if (e instanceof Error && /adopt element handle/.test(e.message)) {
// re-query the element inside the target frame instead
await targetFrame.locator(selector).click();
return;
}
throw e;
} Prevention
- Use Locators scoped to the correct frame instead of cross-frame ElementHandles
- Avoid passing handles across cross-origin iframe boundaries
- Re-query elements in the destination frame when adoption fails
When it happens
Trigger: Adopting an element handle from one frame (especially cross-origin) into another via internal `adoptElementHandle` — reached through `frame.evaluate`/locator logic that passes elements across frame boundaries.
Common situations: Cross-origin iframes in Firefox BiDi; passing ElementHandles between frames in evaluate calls; mixins that reuse handles outside their origin frame.
Related errors
- JSHandle is not a DOM node handle
- Cannot serialize result: object reference chain is too long.
- Method not implemented.
- Not implemented
- Frame has been detached.
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/0f80ae418fd1ae9c.
Report an issue: GitHub.