{"record":{"id":"11740187e1fe237a","repo":"schollz/croc","slug":"sender-did-not-complete-the-croc-pake-handshake","errorCode":null,"errorMessage":"Sender did not complete the croc PAKE handshake","messagePattern":"Sender did not complete the croc PAKE handshake","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/protocol/client.ts","lineNumber":686,"sourceCode":"\n    callbacks.onStatus?.(\"Securing channel…\");\n    const curve = \"p256\";\n    const pake = await wasm().pakeInitWithIdentities(\n      textEncoder.encode(passphrase),\n      0,\n      curve,\n      PAKE_PURPOSE_TRANSFER,\n      room,\n    );\n    await sendControl(control, {\n      t: \"pake\",\n      v: PAKE_PROTOCOL_VERSION,\n      b: pake.bytes,\n      b2: textEncoder.encode(curve),\n    });\n    const peerPake = await receiveControl(control);\n    if (peerPake.t !== \"pake\" || !peerPake.b || !peerPake.b2) {\n      throw new Error(\"Sender did not complete the croc PAKE handshake\");\n    }\n    requirePakeVersion(peerPake.v);\n    if (peerPake.b2.byteLength !== PAKE_SALT_SIZE) {\n      throw new Error(`Sender provided an invalid ${peerPake.b2.byteLength}-byte PAKE salt`);\n    }\n    const finished = await wasm().pakeUpdate(pake.handle, peerPake.b);\n    const peerKeys = await wasm().derivePeerKeys(\n      finished.key,\n      peerPake.b2,\n      PAKE_PURPOSE_TRANSFER,\n      room,\n      curve,\n      pake.bytes,\n      peerPake.b,\n    );\n    await sendControl(control, {\n      t: \"pake-confirm\",\n      v: PAKE_PROTOCOL_VERSION,","sourceCodeStart":668,"sourceCodeEnd":704,"githubUrl":"https://github.com/schollz/croc/blob/e25f1bdc04f07f094d50b0a1bf67e2563944b57a/web/src/protocol/client.ts#L668-L704","documentation":"Thrown by the recipient (receiveFiles) when the reply to its 'pake' message is not a well-formed 'pake' control message (wrong type, or missing b/b2 payload). This is the second step of the croc SPAKE2 handshake over the relay control channel; the sender is expected to answer with its PAKE bytes and the 32-byte salt. Any other message means the peer is not a compatible sender or the channel is desynchronized.","triggerScenarios":"The room was joined by another recipient instead of a sender (both sides sent pake and neither responds correctly); sender aborted between connectRelay and its pake reply, and the relay delivered an error/close frame; version-incompatible peer whose first encrypted message decodes to a different type; malformed relay forwarding.","commonSituations":"Two users both enter receive mode with the same code phrase; one side uses an old client build with a different handshake sequence; relay sends an error message due to room conflicts; testing against a mock sender that does not implement the pake reply.","solutions":["Ensure exactly one sender and one recipient share the code phrase; two recipients cannot handshake","Check the peer's console/error — a mismatch usually fails symmetrically on the other side with 'Recipient did not start a croc PAKE handshake'","Upgrade both peers to the same client version so handshake message ordering matches","If behind the croc relay protocol, verify the relay implementation forwards the raw handshake bytes unchanged"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isPakeMessage(m: { t: string; b?: Uint8Array; b2?: Uint8Array }): boolean {\n  return m.t === \"pake\" && !!m.b && m.b.byteLength > 0 && !!m2check(m.b2);\n  function m2check(b2?: Uint8Array) { return !!b2 && b2.byteLength === 32; }\n}","tryCatchPattern":"catch (e) {\n  if (e instanceof Error && e.message === \"Sender did not complete the croc PAKE handshake\") {\n    // peer is not a compatible sender (possibly another recipient): retry with a fresh code phrase\n  }\n  throw e;\n}","preventionTips":["Ensure exactly one sender and one recipient share a code phrase; coordinate roles before starting","Use long random code phrases so rooms cannot collide","On handshake-type errors, always retry with a NEW code phrase rather than rejoining the same room"],"tags":["pake","handshake","protocol","security"],"backgroundTag":null,"analyzedSha":"e25f1bdc04f07f094d50b0a1bf67e2563944b57a","analyzedAt":"2026-08-15T12:53:39.096Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}