{"record":{"id":"4c3b318db94030ec","repo":"jackwener/OpenCLI","slug":"context-malformed-evaluate-payload","errorCode":null,"errorMessage":"${context}: malformed evaluate payload","messagePattern":"(.+?): malformed evaluate payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/douyin/_shared/evaluate-result.js","lineNumber":13,"sourceCode":"import { CommandExecutionError } from '@jackwener/opencli/errors';\n\nexport function unwrapEvaluateResult(payload) {\n  if (payload && !Array.isArray(payload) && typeof payload === 'object' && 'session' in payload && 'data' in payload) {\n    return payload.data;\n  }\n  return payload;\n}\n\nexport function requireObjectEvaluateResult(payload, context) {\n  const result = unwrapEvaluateResult(payload);\n  if (!result || Array.isArray(result) || typeof result !== 'object') {\n    throw new CommandExecutionError(`${context}: malformed evaluate payload`);\n  }\n  return result;\n}\n","sourceCodeStart":1,"sourceCodeEnd":17,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/_shared/evaluate-result.js#L1-L17","documentation":"requireObjectEvaluateResult unwraps a payload returned from a browser page.evaluate() call and enforces that it is a plain object. If the in-page script returned undefined, null, an array, or a primitive, the library throws this CommandExecutionError with the given context label, because evaluate results that fail to serialize (e.g. returning a DOM node or function) come back as undefined.","triggerScenarios":"A page.evaluate() callback returns undefined (functions/DOM nodes don't serialize), returns null, an array, or a primitive instead of an object; the page navigated mid-evaluate so the script never completed.","commonSituations":"Douyin page DOM changed so the extraction script hits an early return; returning a non-serializable value from evaluate; script error swallowed and resolved with undefined; calling on a page that redirected away from creator.douyin.com.","solutions":["Check the evaluate callback returns a plain object (e.g. return { ok: true, data }) rather than a raw value or nothing.","Log the raw payload before requireObjectEvaluateResult to see what the page actually returned.","Verify the page is still on the expected URL and not redirected/login-gated before evaluating.","Fix the in-page extraction script if Douyin DOM/JS changes made it return early."],"exampleFix":"// before\nconst payload = await page.evaluate(() => document.querySelector('.x')?.innerText);\nconst obj = requireObjectEvaluateResult(payload, 'extract');\n// after\nconst payload = await page.evaluate(() => ({ text: document.querySelector('.x')?.innerText ?? null }));\nconst obj = requireObjectEvaluateResult(payload, 'extract');","handlingStrategy":"type-guard","validationCode":"if (payload === undefined) console.error('evaluate returned undefined — non-serializable return or page navigated away');","typeGuard":"function isObjectPayload(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\nif (!isObjectPayload(raw)) throw new Error('unexpected evaluate payload');","tryCatchPattern":"try {\n  const obj = requireObjectEvaluateResult(payload, 'extract');\n} catch (e) {\n  if (String(e.message).endsWith('malformed evaluate payload')) {\n    console.error('page.evaluate must return a plain object; check the in-page script and current URL');\n  }\n  throw e;\n}","preventionTips":["Always return plain objects from page.evaluate callbacks","Never return DOM nodes, functions, or class instances from evaluate","Check page.url() matches the expected host before evaluating","Wrap in-page extraction in try/catch that returns { ok:false, error } instead of undefined"],"tags":["douyin","puppeteer","page-evaluate","serialization"],"backgroundTag":"malformed-evaluate-payload","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}