stablyai/orca · error · Error
Invalid ${label}: expected ${expected} bytes, got ${bytes.le
Error message
Invalid ${label}: expected ${expected} bytes, got ${bytes.length} What it means
Thrown by `requireLength` inside `deriveMobileE2EEV2KeySchedule` when the shared secret, client nonce, or desktop nonce is not exactly 32 bytes. The HKDF expansion assumes 32-byte inputs; a different length means an upstream cryptographic primitive returned the wrong size (e.g. a truncated X25519 shared secret or a nonce that was not generated by `expo-crypto.getRandomBytes(32)`).
Source
Thrown at mobile/src/transport/mobile-e2ee-v2-key-schedule.ts:46
desktopToMobileKey: expanded.slice(32, 64),
sessionId: expanded.slice(64, 96),
transcriptHash
}
}
function concatBytes(parts: readonly Uint8Array[]): Uint8Array {
const result = new Uint8Array(parts.reduce((total, part) => total + part.length, 0))
let offset = 0
for (const part of parts) {
result.set(part, offset)
offset += part.length
}
return result
}
function requireLength(bytes: Uint8Array, expected: number, label: string): void {
if (bytes.length !== expected) {
throw new Error(`Invalid ${label}: expected ${expected} bytes, got ${bytes.length}`)
}
}
View on GitHub (pinned to 1136503c6a)
Solutions
- Verify the desktop ready message decodes client/desktop nonces to exactly 32 bytes before calling `acceptReady`.
- Confirm `deriveSharedKey` (X25519) is producing 32 bytes — check the pinned desktop public key is a valid 32-byte point.
- Regenerate the client nonce via `ExpoCrypto.getRandomBytes(32)` rather than reusing a buffer of another length.
Example fix
// before
acceptReady({ ..., clientNonce: shortNonce, desktopNonce: shortNonce })
// -> Invalid client nonce: expected 32 bytes, got 16
// after
const clientNonce = ExpoCrypto.getRandomBytes(32)
// validate desktopNonce length before acceptReady:
if (handshake.desktopNonce.length !== 32) throw new Error('bad desktop nonce') Defensive patterns
Strategy: validation
Validate before calling
function validKeyScheduleInputs(sharedSecret: Uint8Array, clientNonce: Uint8Array, desktopNonce: Uint8Array): boolean {
return sharedSecret.length === 32 && clientNonce.length === 32 && desktopNonce.length === 32
}
if (!validKeyScheduleInputs(secret, cNonce, dNonce)) throw new Error('bad crypto lengths') Type guard
function is32Bytes(b: Uint8Array): b is Uint8Array { return b.length === 32 } Try / catch
try { deriveMobileE2EEV2KeySchedule({ sharedSecret, transcript, clientNonce, desktopNonce }) } catch (e) { if (e.message.startsWith('Invalid ')) { /* abort handshake, log which input was wrong size */ } else throw e } Prevention
- Generate nonces only via ExpoCrypto.getRandomBytes(32).
- Validate the pinned desktop public key decodes to 32 bytes before pairing.
- Reject handshakes whose decoded nonces are not 32 bytes upstream of acceptReady.
When it happens
Trigger: `acceptReady` invoked with a `handshake.clientNonce`/`handshake.desktopNonce` that is not 32 bytes; `deriveSharedKey` returning something other than 32 bytes due to a malformed public key; a key schedule test passing hand-rolled buffers of the wrong length.
Common situations: Corrupted or base64-decoded-with-wrong-alphabet nonce from the desktop; a pre-release desktop that sends 16-byte nonces; tests that hand-construct a handshake without respecting the 32-byte contract; a public key from `publicKeyFromBase64` that decoded to a non-32-byte scalar.
Related errors
- Invalid public key: expected 32 bytes, got ${key.length} fro
- Invalid client nonce length: ${clientNonce.length}
- E2EE v2 ready has not been accepted
- Package version is not valid semver: ${baseVersion}
- Adhoc build timestamp is invalid.
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/b242045f054133fa.
Report an issue: GitHub.