{"record":{"id":"0b3d3f6caac81d6d","repo":"jackwener/OpenCLI","slug":"twitter-x-label-returned-a-malformed-browser-br","errorCode":null,"errorMessage":"Twitter/X ${label} returned a malformed Browser Bridge envelope","messagePattern":"Twitter/X (.+?) returned a malformed Browser Bridge envelope","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/auth.js","lineNumber":20,"sourceCode":"import { registerSiteAuthCommands } from '../_shared/site-auth.js';\nimport { normalizeTwitterScreenName } from './shared.js';\n\nconst SCREEN_NAME_POLL_SECONDS = 1;\nconst SCREEN_NAME_POLLS = 8;\nconst SCREEN_NAME_AGREEMENTS = 3;\n\nasync function hasTwitterSessionCookies(page) {\n  const cookies = await page.getCookies({ url: 'https://x.com' });\n  const names = new Set(cookies.map(cookie => cookie.name));\n  return names.has('auth_token') && names.has('ct0');\n}\n\nfunction unwrapTwitterEvaluateResult(value, label) {\n  if (value && typeof value === 'object' && !Array.isArray(value) && 'session' in value) {\n    if (typeof value.session === 'string' && Object.prototype.hasOwnProperty.call(value, 'data')) {\n      return value.data;\n    }\n    throw new CommandExecutionError(`Twitter/X ${label} returned a malformed Browser Bridge envelope`);\n  }\n  return value;\n}\n\nasync function readScreenName(page) {\n  const href = unwrapTwitterEvaluateResult(await page.evaluate(`() => {\n    const link = document.querySelector('a[data-testid=\"AppTabBar_Profile_Link\"]');\n    return link ? link.getAttribute('href') : null;\n  }`), 'profile link probe');\n  if (href !== null && typeof href !== 'string') {\n    throw new CommandExecutionError('Twitter/X profile link probe returned a malformed href');\n  }\n  return normalizeTwitterScreenName(typeof href === 'string' ? href : '');\n}\n\n/**\n * Right after an account switch the home surface keeps showing the previous\n * account for a few seconds, so a single read misreports it (#2252); trust","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/auth.js#L2-L38","documentation":"unwrapTwitterEvaluateResult validates the Browser Bridge envelope for Twitter/X evaluate calls. A valid envelope is an object with a string session field and a data property; if the object has session but lacks data (or session is not a string), the wrapper concludes the envelope is malformed and throws CommandExecutionError. This protects callers from consuming corrupted bridge results.","triggerScenarios":"page.evaluate (via unwrapTwitterEvaluateResult, e.g. from readScreenName's href call) returned an object containing a session key but no data key, or session is not a string.","commonSituations":"Browser Bridge extension upgraded or downgraded to a version with a different envelope format; multiple extension versions installed; bridge returning an error object that coincidentally includes a session field.","solutions":["Reload the browser and the extension so the bridge restarts with the current envelope format.","Verify the Browser Bridge extension version matches what the CLI expects; update whichever is stale.","Re-run the command; transient bridge races can produce partial envelopes.","Capture the raw evaluate value to confirm the envelope shape before reporting a bug."],"exampleFix":"// before\nconst value = await page.evaluate('() => location.href');\n// after\nconst value = unwrapTwitterEvaluateResult(await page.evaluate('() => location.href'), 'href probe');\nif (typeof value !== 'string') throw new Error('Unexpected href probe result');","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isBridgeEnvelope(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v) && 'session' in v;\n}\nfunction isWellFormedEnvelope(v) {\n  return !isBridgeEnvelope(v) || (typeof v.session === 'string' && 'data' in v);\n}","tryCatchPattern":"try {\n  const data = unwrapTwitterEvaluateResult(await page.evaluate(src), 'probe');\n} catch (e) {\n  if (/malformed Browser Bridge envelope/.test(e.message)) {\n    await reloadExtension();\n    return retry();\n  }\n  throw e;\n}","preventionTips":["Restart browser/extension after any CLI or extension upgrade","Pin matching CLI + extension versions","Avoid running multiple extension versions in one profile","Retry once — transient bridge races can emit partial envelopes"],"tags":["browser-bridge","envelope","contract-violation"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}