{"record":{"id":"7ed38c20b2665a17","repo":"microsoft/playwright","slug":"only-element-handles-can-be-evaluated-in-the-params-world","errorCode":null,"errorMessage":"Only element handles can be evaluated in the \"${params.world}\" world","messagePattern":"Only element handles can be evaluated in the \"(.+?)\" world","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/dispatchers/jsHandleDispatcher.ts","lineNumber":47,"sourceCode":"\nexport class JSHandleDispatcher<ParentScope extends JSHandleDispatcherParentScope = JSHandleDispatcherParentScope> extends Dispatcher<js.JSHandle, channels.JSHandleChannel, ParentScope> implements channels.JSHandleChannel {\n  _type_JSHandle = true;\n\n  static fromJSHandle(scope: JSHandleDispatcherParentScope, handle: js.JSHandle): JSHandleDispatcher {\n    return scope.connection.existingDispatcher<JSHandleDispatcher>(handle) || new JSHandleDispatcher(scope, handle);\n  }\n\n  protected constructor(scope: ParentScope, jsHandle: js.JSHandle) {\n    // Do not call this directly, use createHandle() instead.\n    super(scope, jsHandle, jsHandle.asElement() ? 'ElementHandle' : 'JSHandle', {\n      preview: jsHandle.toString(),\n    });\n    jsHandle._setPreviewCallback(preview => this._dispatchEvent('previewUpdated', { preview }));\n  }\n\n  async evaluateExpression(params: channels.JSHandleEvaluateExpressionParams, progress: Progress): Promise<channels.JSHandleEvaluateExpressionResult> {\n    if (params.world)\n      throw new Error(`Only element handles can be evaluated in the \"${params.world}\" world`);\n    const jsHandle = await this._object.evaluateExpression(progress, params.expression, { isFunction: params.isFunction, serialize: params.serialize }, parseArgument(params.arg));\n    return { value: serializeResult(jsHandle, params) };\n  }\n\n  async evaluateExpressionHandle(params: channels.JSHandleEvaluateExpressionHandleParams, progress: Progress): Promise<channels.JSHandleEvaluateExpressionHandleResult> {\n    const jsHandle = await this._object.evaluateExpressionHandle(progress, params.expression, { isFunction: params.isFunction, serialize: params.serialize }, parseArgument(params.arg));\n    // If \"jsHandle\" is an ElementHandle, it belongs to the same frame as \"this\".\n    return { handle: ElementHandleDispatcher.fromJSOrElementHandle(this.parentScope() as FrameDispatcher, jsHandle) };\n  }\n\n  async getProperty(params: channels.JSHandleGetPropertyParams, progress: Progress): Promise<channels.JSHandleGetPropertyResult> {\n    const jsHandle = await this._object.getProperty(progress, params.name);\n    // If \"jsHandle\" is an ElementHandle, it belongs to the same frame as \"this\".\n    return { handle: ElementHandleDispatcher.fromJSOrElementHandle(this.parentScope() as FrameDispatcher, jsHandle) };\n  }\n\n  async getPropertyList(params: channels.JSHandleGetPropertyListParams, progress: Progress): Promise<channels.JSHandleGetPropertyListResult> {\n    const map = await this._object.getProperties(progress);","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/microsoft/playwright/blob/f1d33b5029be8bbc1095fe88e559117fa3a6243b/packages/playwright-core/src/server/dispatchers/jsHandleDispatcher.ts#L29-L65","documentation":"JSHandleDispatcher.evaluateExpression throws when a world ('main' or 'utility') is requested for an expression evaluated on a plain JSHandle. Execution worlds only make sense for ElementHandle, whose element can be moved into a specific world; the base JSHandle dispatcher unconditionally rejects params.world.","triggerScenarios":"Calling jsHandle.evaluateExpression(expression, { world: 'utility' }) or passing a world option through an evaluate call routed at a non-element handle (e.g. a page.evaluateHandle result).","commonSituations":"Reusing an evaluate helper written for locators/element handles and passing a plain JSHandle; adding world options to generic handle evaluation for isolation reasons.","solutions":["Omit the world option when evaluating on a plain JSHandle.","Use locator.evaluate or elementHandle.evaluateExpression with the world option instead — worlds are only supported for element handles.","If you need the value in a specific world, evaluate on the page/frame and pass the handle as an argument."],"exampleFix":"// before\nconst handle = await page.evaluateHandle('window.foo');\nawait handle.evaluateExpression('el => el', { world: 'utility' });\n// after\nawait page.locator('#target').evaluate('el => el', undefined, { world: 'utility' });","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function canUseWorld(handle: unknown): handle is import('playwright-core').ElementHandle {\n  return !!handle && typeof (handle as any).evaluateExpression === 'function' && (handle as any)._element !== undefined;\n}\n// simpler: only pass world when the subject is a Locator / ElementHandle","tryCatchPattern":"try {\n  return await handle.evaluateExpression(expr, { world: 'utility' });\n} catch (e) {\n  if (String(e.message).includes('Only element handles')) return await handle.evaluateExpression(expr);\n  throw e;\n}","preventionTips":["Only attach world options to locator/elementHandle evaluations, never to JSHandle evaluations.","Keep a single evaluate helper that conditionally includes world based on subject type."],"tags":["evaluate","world","jshandle","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"f1d33b5029be8bbc1095fe88e559117fa3a6243b","analyzedAt":"2026-09-21T21:58:31.278Z","contentChangedAt":"2026-09-21T21:58:31.278Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}