{"record":{"id":"cfd30b8215cc2c6f","repo":"jackwener/OpenCLI","slug":"gmail-label-returned-a-malformed-browser-bridge","errorCode":null,"errorMessage":"Gmail ${label} returned a malformed Browser Bridge envelope","messagePattern":"Gmail (.+?) returned a malformed Browser Bridge envelope","errorType":"error_code","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gmail/utils.js","lineNumber":22,"sourceCode":"  CommandExecutionError,\n  EmptyResultError,\n  TimeoutError,\n} from '@jackwener/opencli/errors';\n\nexport const GMAIL_ORIGIN = 'https://mail.google.com';\nexport const GMAIL_HOST = 'mail.google.com';\nexport const DEFAULT_LIMIT = 20;\nexport const MAX_LIMIT = 200;\nconst PAGE_SIZE = 50;\nconst CAPTURE_WAIT_SECONDS = 10;\nconst MAX_BODY_CHARS = 20_000;\n\nexport function unwrapBrowserResult(value, label = 'browser probe') {\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(`Gmail ${label} returned a malformed Browser Bridge envelope`);\n  }\n  return value;\n}\n\nexport function parseLimit(raw, fallback = DEFAULT_LIMIT, max = MAX_LIMIT) {\n  const value = raw ?? fallback;\n  const limit = Number(value);\n  if (!Number.isInteger(limit) || limit <= 0) {\n    throw new ArgumentError('limit must be a positive integer');\n  }\n  if (limit > max) {\n    throw new ArgumentError(`limit must be <= ${max}`);\n  }\n  return limit;\n}\n\nexport function parseAccount(raw) {\n  const value = raw ?? 0;","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gmail/utils.js#L4-L40","documentation":"unwrapBrowserResult validates that browser responses use the Browser Bridge envelope shape { session: string, data: ... }. If an object carries a `session` key but is missing `data` or has a non-string session, the envelope is malformed and the library throws CommandExecutionError rather than returning corrupt data.","triggerScenarios":"The Browser Bridge returns an object with a `session` property but no `data` property, or session is not a string — e.g. a version mismatch between the CLI and bridge where the envelope contract changed, or the bridge returned an error object containing a session-like field.","commonSituations":"Upgrading the CLI without upgrading the browser bridge extension (or vice versa); a proxy/middleware rewrites the response shape; the bridge returns an error payload with a `session` field that collides with the envelope protocol.","solutions":["Update the Browser Bridge extension and the gmail CLI to matching versions so the envelope contract ({session: string, data}) is respected.","Inspect the raw value returned by the bridge to see what shape is actually being produced.","Check for intermediary code that wraps or rewrites the bridge response and accidentally adds/removes a `session` or `data` key.","Retry the browser request; a transient bridge failure may produce a partial envelope."],"exampleFix":"// before (bridge v1 response, old envelope)\n{ session: 'abc' } // no data -> malformed\n// after: upgrade bridge so it returns\n{ session: 'abc', data: { rows: [...] } }","handlingStrategy":"type-guard","validationCode":"const isEnvelope = (v) => v && typeof v === 'object' && !Array.isArray(v) &&\n  ('session' in v ? typeof v.session === 'string' && 'data' in v : true);","typeGuard":"function isBridgeEnvelope(v) {\n  return !!v && typeof v === 'object' && !Array.isArray(v) &&\n    typeof v.session === 'string' && Object.prototype.hasOwnProperty.call(v, 'data');\n}","tryCatchPattern":"try {\n  rows = unwrapBrowserResult(raw, 'search');\n} catch (e) {\n  if (/malformed Browser Bridge envelope/.test(e.message)) {\n    console.error('Bridge/CLI version mismatch — update both');\n  }\n  throw e;\n}","preventionTips":["Keep the Browser Bridge extension and CLI on matching versions.","Add a version handshake/compat check at bridge connect time.","Avoid passing objects with a `session` key through bridge responses unless they are real envelopes.","Log raw bridge payloads in debug mode to catch shape drift early."],"tags":["browser-bridge","envelope","contract-mismatch"],"backgroundTag":"response-envelope-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}