{"record":{"id":"ed45fe08241213d7","repo":"stablyai/orca","slug":"invalid-e2ee-v2-authenticated-response","errorCode":null,"errorMessage":"Invalid E2EE v2 authenticated response","messagePattern":"Invalid E2EE v2 authenticated response","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mobile/src/transport/mobile-e2ee-v2-physical-channel.ts","lineNumber":111,"sourceCode":"    }\n    if (this.state === 'awaiting-ready') {\n      this.acceptReady(raw)\n      return\n    }\n\n    const plaintext =\n      typeof raw === 'string'\n        ? this.args.session.openText(raw)\n        : await this.openBinary(raw, generation)\n    if (generation !== this.generation || plaintext === null) {\n      return\n    }\n    if (this.state === 'awaiting-authenticated') {\n      if (typeof plaintext === 'string' && isAuthenticationRejection(plaintext)) {\n        throw new MobileE2EEAuthenticationError()\n      }\n      if (typeof plaintext !== 'string' || !this.isAuthenticated(plaintext)) {\n        throw new Error('Invalid E2EE v2 authenticated response')\n      }\n      this.state = 'ready'\n      this.args.onAuthenticated()\n    } else if (typeof plaintext === 'string') {\n      this.args.onText(plaintext)\n    } else {\n      this.args.onBinary(plaintext)\n    }\n  }\n\n  private acceptReady(raw: unknown): void {\n    if (typeof raw !== 'string') {\n      throw new Error('Expected plaintext E2EE v2 ready')\n    }\n    let ready: unknown\n    try {\n      ready = JSON.parse(raw)\n    } catch {","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/transport/mobile-e2ee-v2-physical-channel.ts#L93-L129","documentation":"Thrown in the `awaiting-authenticated` state when the decrypted plaintext is a string but does not satisfy `isAuthenticated` — i.e. it is not a JSON object with exactly the keys `transcriptHashB64,type,v`, or `type !== 'e2ee_authenticated'`, or `v !== 2`, or the transcript hash does not equal the session's. Unlike an explicit `e2ee_error` rejection, this is a malformed or unexpected authenticated-shaped response.","triggerScenarios":"Desktop sent a non-rejection, non-authenticated plaintext during the auth window (e.g. a stray text frame); transcript-hash mismatch where neither side sent `e2ee_error`; a version-skewed desktop that uses a different authenticated schema or extra keys.","commonSituations":"Protocol version drift between mobile and desktop; a desktop bug that ships a mis-specified `e2ee_authenticated` message with extra fields; man-in-the-middle or corrupted frame that decrypts to plausible-but-wrong JSON.","solutions":["Confirm desktop and mobile are on the same v2 e2ee contract version.","Inspect the decrypted plaintext (via a debug hook) to see which `isAuthenticated` branch failed — extra keys, wrong type, or hash mismatch each point to a different cause.","Treat as fatal for the link and tear down + retry the full handshake."],"exampleFix":"// before\nonError: (e) => log(e.message) // no recovery\n\n// after\nonError: (e) => {\n  if (e.message === 'Invalid E2EE v2 authenticated response') {\n    reportProtocolMismatchAndDisconnect(link)\n  } else { /* ... */ }\n}","handlingStrategy":"try-catch","validationCode":"// No preventive call: the desktop sent a bad authenticated message. Validate after decrypt in a debug hook.","typeGuard":"function isAuthenticatedShape(msg: unknown): boolean {\n  if (typeof msg !== 'object' || msg === null) return false\n  const keys = Object.keys(msg).sort().join(',')\n  return keys === 'transcriptHashB64,type,v'\n}","tryCatchPattern":"channel.onError = (e) => { if (e.message === 'Invalid E2EE v2 authenticated response') { reportProtocolMismatch(link); link.close() } else { /* ... */ } }","preventionTips":["Version-negotiate e2ee v2 up front so schema drift is impossible.","Tear down the link on this error — do not retry with the same peer.","Log the decrypted plaintext (debug only) to identify which branch of isAuthenticated failed."],"tags":["e2ee","authentication","protocol-version","handshake"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}