{"record":{"id":"4cccbdf3193186ed","repo":"microsoft/playwright","slug":"passed-function-is-not-well-serializable","errorCode":null,"errorMessage":"Passed function is not well-serializable!","messagePattern":"Passed function is not well-serializable!","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/javascript.ts","lineNumber":323,"sourceCode":"\nexport function normalizeEvaluationExpression(expression: string, isFunction: boolean | undefined): string {\n  expression = expression.trim();\n\n  if (isFunction) {\n    try {\n      new Function('(' + expression + ')');\n    } catch (e1) {\n      // This means we might have a function shorthand. Try another\n      // time prefixing 'function '.\n      if (expression.startsWith('async '))\n        expression = 'async function ' + expression.substring('async '.length);\n      else\n        expression = 'function ' + expression;\n      try {\n        new Function('(' + expression  + ')');\n      } catch (e2) {\n        // We tried hard to serialize, but there's a weird beast here.\n        throw new Error('Passed function is not well-serializable!');\n      }\n    }\n  }\n\n  if (/^(async)?\\s*function(\\s|\\()/.test(expression))\n    expression = '(' + expression + ')';\n  return expression;\n}\n\n// Error inside the expression evaluation as opposed to a protocol error.\nexport class JavaScriptErrorInEvaluate extends Error {\n}\n\nexport function isJavaScriptErrorInEvaluate(error: Error) {\n  return error instanceof JavaScriptErrorInEvaluate;\n}\n\nexport function sparseArrayToString(entries: { name: string, value?: any }[]): string {","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/javascript.ts#L305-L341","documentation":"Thrown by normalizeEvaluationExpression() when a function passed to page.evaluate() or similar cannot be parsed by the JavaScript engine even after wrapping attempts. The function first tries new Function('(' + expression + ')'), and if that fails, prepends 'function ' or 'async function ' and retries. If both attempts produce a SyntaxError, the function is considered not well-serializable.","triggerScenarios":"Passing a function that relies on closure variables (these cannot be serialized), uses non-standard syntax, or is an async generator. Also triggered by functions that use syntax constructs that break when wrapped in new Function(). Arrow functions with implicit returns of objects, or functions using features not supported by the runtime's parser.","commonSituations":"Passing an arrow function that references an outer variable (closure). Passing a function that uses 'await' without 'async'. Passing a class constructor or generator function. Functions with JSX or TypeScript syntax not transpiled before evaluation. Functions that reference 'this' from the calling context.","solutions":["Ensure the function is self-contained with no closure references — pass all needed values as arguments.","Use page.evaluate() with explicit argument passing: page.evaluate((a, b) => a + b, x, y) instead of () => x + y.","If the function is complex, define it as a string expression or use addInitScript to pre-load it."],"exampleFix":"// before\nconst threshold = 100;\nawait page.evaluate(() => document.querySelectorAll('.item').length > threshold); // closure ref\n\n// after\nconst threshold = 100;\nawait page.evaluate(threshold => document.querySelectorAll('.item').length > threshold, threshold);","handlingStrategy":"validation","validationCode":"// Ensure function is self-contained: no closure references\nfunction isSelfContained(fn) {\n  try {\n    new Function('(' + fn.toString() + ')');\n    return true;\n  } catch {\n    try {\n      new Function('(function ' + fn.toString().replace(/^async ?/, 'async ') + ')');\n      return true;\n    } catch { return false; }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass all external values as arguments, not via closure.","Avoid referencing 'this' from outer scope in evaluate functions.","Test evaluate functions in isolation to catch serialization issues early."],"tags":["evaluate","serialization","javascript","closure","function"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}