stablyai/orca · error · Error
Invalid E2EE v2 ready
Error message
Invalid E2EE v2 ready
What it means
Thrown by `acceptReady` when the ready JSON parsed successfully but `session.acceptReady(ready)` returned `false`. That boolean is false when `validateMobileE2EEV2Handshake` rejects the shape, or when the desktop public key in the handshake does not constant-time-equal the pinned key. This is the cryptographic pin check failing.
Source
Thrown at mobile/src/transport/mobile-e2ee-v2-physical-channel.ts:133
} else if (typeof plaintext === 'string') {
this.args.onText(plaintext)
} else {
this.args.onBinary(plaintext)
}
}
private acceptReady(raw: unknown): void {
if (typeof raw !== 'string') {
throw new Error('Expected plaintext E2EE v2 ready')
}
let ready: unknown
try {
ready = JSON.parse(raw)
} catch {
throw new Error('Invalid E2EE v2 ready JSON')
}
if (!this.args.session.acceptReady(ready)) {
throw new Error('Invalid E2EE v2 ready')
}
this.state = 'awaiting-authenticated'
this.outboundQueue.enqueue({
kind: 'text',
plaintext: JSON.stringify({
type: 'e2ee_auth',
v: 2,
transcriptHashB64: this.args.session.transcriptHashB64,
deviceToken: this.args.deviceToken
})
})
}
private async openBinary(raw: unknown, generation: number): Promise<Uint8Array | null> {
const bytes = await this.args.decodeBinary(raw)
if (!bytes || generation !== this.generation) {
return null
}View on GitHub (pinned to 1136503c6a)
Solutions
- Confirm the `desktopPublicKeyB64` passed to `MobileE2EEV2ClientSession.create` matches the host's current long-term key (re-pair if the desktop rotated keys).
- Inspect the ready payload against `validateMobileE2EEV2Handshake` to see whether schema or pin failed.
- Abort the link on this error — do not retry with the same pin.
Example fix
// before
session.acceptReady(ready) // silently false, then channel throws
// after
const handshake = validateMobileE2EEV2Handshake(session.hello, ready)
if (!handshake) reportError('ready schema rejected')
else if (!equalBytes(handshake.desktopPublicKey, pinnedDesktopPublicKey))
reportError('desktop key pin mismatch — re-pair required') Defensive patterns
Strategy: validation
Validate before calling
import { validateMobileE2EEV2Handshake } from '../../../src/shared/mobile-e2ee-v2-contract'
const handshake = validateMobileE2EEV2Handshake(session.hello, readyPayload)
if (!handshake || !equalBytes(handshake.desktopPublicKey, pinnedDesktopPublicKey)) {
// abort before acceptReady
} Type guard
function pinsDesktopKey(handshake: { desktopPublicKey: Uint8Array } | null, pinned: Uint8Array): boolean {
return !!handshake && equalBytes(handshake.desktopPublicKey, pinned)
} Try / catch
channel.onError = (e) => { if (e.message === 'Invalid E2EE v2 ready') { markHostForRepair(hostId); link.close() } } Prevention
- Keep the pinned desktop public key in sync with the host's current long-term key.
- Treat a pin mismatch as a re-pair trigger, never a retry.
- Validate the ready schema before trusting any field.
When it happens
Trigger: Desktop's `desktopPublicKey` in the ready message differs from the `pinnedDesktopPublicKey` configured at session creation; ready message schema mismatch (wrong fields, wrong version, missing nonce); a different host answered the relay connection than the one the mobile pinned.
Common situations: Pinning the wrong public key (stale host profile after a desktop re-install); connecting to the wrong host via relay; a man-in-the-middle attempt that cannot produce the pinned key; protocol version skew where the ready schema changed.
Related errors
- E2EE v2 ready has not been accepted
- E2EE device authentication rejected
- Invalid E2EE v2 authenticated response
- Expected plaintext E2EE v2 ready
- Invalid E2EE v2 ready JSON
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/df485aef6116d258.
Report an issue: GitHub.