{"record":{"id":"3b7603df6fceb4f1","repo":"microsoft/playwright","slug":"cannot-serialize-result-object-reference-chain-is-3b7603","errorCode":null,"errorMessage":"Cannot serialize result: object reference chain is too long.","messagePattern":"Cannot serialize result: object reference chain is too long\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/webkit/wkExecutionContext.ts","lineNumber":123,"sourceCode":"    if (!handle._objectId)\n      return;\n    await this._session.send('Runtime.releaseObject', { objectId: handle._objectId });\n  }\n\n  shouldPrependErrorPrefix(): boolean {\n    return false;\n  }\n}\n\nfunction potentiallyUnserializableValue(remoteObject: Protocol.Runtime.RemoteObject): any {\n  const value = remoteObject.value;\n  const isUnserializable = remoteObject.type === 'number' && ['NaN', '-Infinity', 'Infinity', '-0'].includes(remoteObject.description!);\n  return isUnserializable ? js.parseUnserializableValue(remoteObject.description!) : value;\n}\n\nfunction rewriteError(error: Error): Error {\n  if (error.message.includes('Object has too long reference chain'))\n    throw new Error('Cannot serialize result: object reference chain is too long.');\n  if (!js.isJavaScriptErrorInEvaluate(error) && !isSessionClosedError(error))\n    return new Error('Execution context was destroyed, most likely because of a navigation.');\n  return error;\n}\n\nfunction renderPreview(object: Protocol.Runtime.RemoteObject): string | undefined {\n  if (object.type === 'undefined')\n    return 'undefined';\n  if ('value' in object)\n    return String(object.value);\n\n  if (object.description === 'Object' && object.preview) {\n    const tokens = [];\n    for (const { name, value } of object.preview.properties!)\n      tokens.push(`${name}: ${value}`);\n    return `{${tokens.join(', ')}}`;\n  }\n  if (object.subtype === 'array' && object.preview)","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/webkit/wkExecutionContext.ts#L105-L141","documentation":"rewriteError() in wkExecutionContext converts the engine's 'Object has too long reference chain' message into a user-facing error. WebKit refuses to serialize remote objects whose reference graph is too deep to traverse, so returning such an object from page.evaluate/evaluateHandle fails serialization.","triggerScenarios":"Returning a deeply-nested or self-referential object from page.evaluate/evaluateHandle (e.g. returning window, a DOM node with huge subtrees, or a circular structure). Also when an evaluate returns an object whose serialized form exceeds WebKit's internal depth cap.","commonSituations":"Accidentally returning a live DOM node/window from evaluate instead of a primitive. Returning application state objects with long prototype chains or large arrays. Snapshotting big component trees for inspection.","solutions":["Return only serializable primitives or shallow plain objects from evaluate; project the fields you need inside the page.","For DOM nodes use evaluateHandle + explicit property reads, or return specific attributes/text instead of the node graph.","Break circular references before returning, or JSON-serialize inside the page and parse outside."],"exampleFix":"// before\nconst x = await page.evaluate(() => window);\n\n// after\nconst x = await page.evaluate(() => ({ origin: window.location.origin, ua: navigator.userAgent }));","handlingStrategy":"validation","validationCode":"// Keep evaluate return values shallow and primitive-typed.\nconst summary = await page.evaluate(() => ({\n  origin: location.origin,\n  title: document.title,\n}));","typeGuard":"function isSafeSerializable(v: unknown): boolean {\n  if (v === null || typeof v !== 'object') return typeof v !== 'function';\n  try { JSON.stringify(v); return true; } catch { return false; }\n}","tryCatchPattern":"let result;\ntry { result = await page.evaluate(() => window); }\ncatch (e) {\n  if (/reference chain is too long/.test(e.message))\n    result = await page.evaluate(() => ({ origin: location.origin }));\n  else throw e;\n}","preventionTips":["Never return window/document/large live nodes from evaluate.","Project to plain fields inside the page before returning."],"tags":["webkit","evaluate","serialization","execution-context"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}