{"record":{"id":"fc2361f7d2ecf7d5","repo":"microsoft/playwright","slug":"jshandles-can-be-evaluated-only-in-the-context-the","errorCode":null,"errorMessage":"JSHandles can be evaluated only in the context they were created!","messagePattern":"JSHandles can be evaluated only in the context they were created!","errorType":"exception","errorClass":"JavaScriptErrorInEvaluate","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/javascript.ts","lineNumber":280,"sourceCode":"  args = args.map(arg => serializeAsCallArgument(arg, handle => {\n    if (handle instanceof JSHandle) {\n      if (!handle._objectId)\n        return { fallThrough: handle._value };\n      if (handle._disposed)\n        throw new JavaScriptErrorInEvaluate('JSHandle is disposed!');\n      const adopted = context.adoptIfNeeded(handle);\n      if (adopted === null)\n        return { h: pushHandle(Promise.resolve(handle)) };\n      toDispose.push(adopted);\n      return { h: pushHandle(adopted) };\n    }\n    return { fallThrough: handle };\n  }));\n\n  const utilityScriptObjects: JSHandle[] = [];\n  for (const handle of await Promise.all(handles)) {\n    if (handle._context !== context)\n      throw new JavaScriptErrorInEvaluate('JSHandles can be evaluated only in the context they were created!');\n    utilityScriptObjects.push(handle);\n  }\n\n  // See UtilityScript for arguments.\n  const utilityScriptValues = [options.isFunction, options.returnByValue, expression, args.length, ...args];\n\n  const script = `(utilityScript, ...args) => utilityScript.evaluate(...args)`;\n  try {\n    return await context._evaluateWithArguments(script, options.returnByValue || false, utilityScriptValues, utilityScriptObjects);\n  } finally {\n    toDispose.map(handlePromise => handlePromise.then(handle => handle.dispose()));\n  }\n}\n\nexport function parseUnserializableValue(unserializableValue: string): any {\n  if (unserializableValue === 'NaN')\n    return NaN;\n  if (unserializableValue === 'Infinity')","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/javascript.ts#L262-L298","documentation":"Thrown as a JavaScriptErrorInEvaluate by evaluateExpression() when a JSHandle being passed as an argument belongs to a different ExecutionContext than the one the evaluate is running in. Each frame (and each isolated world) has its own context; handles created in one cannot be referenced in another. The check compares handle._context against the target context.","triggerScenarios":"Passing a JSHandle from Frame A's context to an evaluate on Frame B. Using a handle from the main world in an evaluate running in the utility world. Using a handle from a previous page in the current page's evaluate. Cross-origin iframe handles used in the parent frame's evaluate.","commonSituations":"Storing a handle from one frame and using it in another frame's evaluate. Handle created before a navigation that created a new context. Mixing handles from addInitScript-injected scripts with main-context evaluates. Using a handle from an isolated world (e.g., from a selector engine) in a regular evaluate.","solutions":["Create the JSHandle in the same frame/context where it will be used in evaluate.","Re-query elements in the target frame instead of passing handles across frames.","Extract serializable values (strings, numbers) from the handle before crossing context boundaries: const value = await handle.jsonValue().","For cross-frame operations, use element handles' own evaluate methods which run in the element's context."],"exampleFix":"// before\nconst handleFromFrameA = await frameA.evaluateHandle('document');\nawait frameB.evaluate(h => h.title, handleFromFrameA); // throws [335]\n\n// after\nconst title = await frameA.evaluate(() => document.title);\n// use the serializable value in frameB if needed","handlingStrategy":"validation","validationCode":"// Extract serializable value before crossing context boundaries\nconst value = await handle.jsonValue();\n// Now pass the plain value instead of the handle","typeGuard":null,"tryCatchPattern":"try {\n  await frame.evaluate(fn, handle);\n} catch (e) {\n  if (e.message.includes('only in the context they were created')) {\n    const json = await handle.jsonValue();\n    return frame.evaluate(fn, json);\n  }\n  throw e;\n}","preventionTips":["Create handles in the same frame where they will be used.","Extract serializable values before crossing frame/context boundaries.","Use element.evaluateInUtility or element.evaluate for element-scoped evaluation."],"tags":["jshandle","evaluate","execution-context","javascript","cross-frame"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}