stablyai/orca · error · Error
Invalid E2EE v2 ready JSON
Error message
Invalid E2EE v2 ready JSON
What it means
Thrown by `acceptReady` when the first frame is a string but `JSON.parse` throws — the ready payload is not valid JSON. The catch block re-wraps the parse failure so callers see a single, specific cause rather than a raw `SyntaxError`.
Source
Thrown at mobile/src/transport/mobile-e2ee-v2-physical-channel.ts:130
}
this.state = 'ready'
this.args.onAuthenticated()
} 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)View on GitHub (pinned to 1136503c6a)
Solutions
- Log the raw first frame to identify what non-JSON content arrived.
- Verify the relay/desktop endpoint is the intended one and not returning an HTTP/HTML error body.
- Ensure the channel is not shared with debug logging.
Example fix
// before
// opaque: only see "Invalid E2EE v2 ready JSON"
// after
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 (e) { throw new Error(`Invalid E2EE v2 ready JSON: ${raw.slice(0, 120)}`) }
// ...
} Defensive patterns
Strategy: try-catch
Validate before calling
function isJsonString(s: string): boolean { try { JSON.parse(s); return true } catch { return false } }
if (typeof firstFrame === 'string' && !isJsonString(firstFrame)) { /* log raw, close */ } Try / catch
channel.onError = (e) => { if (e.message === 'Invalid E2EE v2 ready JSON') { logRawFirstFrameForDiagnosis(); link.close() } } Prevention
- Log the raw first frame to identify non-JSON content (error pages, debug logs).
- Verify the relay/desktop endpoint returns the ready handshake, not an error body.
- Guard the channel against shared debug logging.
When it happens
Trigger: Desktop sent a ready frame that is plain text but not JSON (e.g. an HTTP error body, a debug log, or a partial/truncated frame); a proxy or relay injected non-JSON text; encoding mismatch (UTF-16 BOM, etc.) that breaks the JSON lexer.
Common situations: A misbehaving relay returning an error page on the WebSocket; desktop build that logs to the same channel; truncation at a transport boundary producing half a JSON document.
Related errors
- E2EE v2 ready has not been accepted
- Invalid E2EE v2 authenticated response
- Expected plaintext E2EE v2 ready
- Invalid E2EE v2 ready
- invalid relay hello JSON
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/3974d8423daf69fd.
Report an issue: GitHub.