schollz/croc · error · Error

Recipient PAKE confirmation failed

Error message

Recipient PAKE confirmation failed

What it means

The recipient's key-confirmation bytes failed verification via wasm().confirmPeerKey, meaning the two sides derived different PAKE keys. With the protocol version already matched, the overwhelmingly common cause is that the two parties typed different code phrases. Verification failing here is a security feature: it prevents continuing with mismatched keys.

Source

Thrown at web/src/protocol/client.ts:444

      PAKE_PURPOSE_TRANSFER,
      room,
      curve,
      peerPake.b,
      finished.bytes,
    );
    await sendControl(control, {
      t: "pake",
      v: PAKE_PROTOCOL_VERSION,
      b: finished.bytes,
      b2: salt,
    });
    const confirmationA = await receiveControl(control);
    if (confirmationA.t !== "pake-confirm" || !confirmationA.b) {
      throw new Error("Recipient did not confirm the croc PAKE handshake");
    }
    requirePakeVersion(confirmationA.v);
    if (!(await wasm().confirmPeerKey(peerKeys.confirmationA, confirmationA.b))) {
      throw new Error("Recipient PAKE confirmation failed");
    }
    await sendControl(control, {
      t: "pake-confirm",
      v: PAKE_PROTOCOL_VERSION,
      b: peerKeys.confirmationB,
    });
    key = peerKeys.key;

    callbacks.onStatus?.("Opening encrypted data channels…");
    data = await openDataConnections(
      settings,
      room,
      dataPorts(relay.banner),
      signal,
    );

    const peerIP = await receiveControl(control, key);
    if (peerIP.t !== "externalip") throw new Error("Recipient did not secure the channel");

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Re-share the exact same code phrase to both sides (copy-paste, not retype) and retry
  2. Strip surrounding whitespace when reading the code into the client
  3. Prefer the auto-generated code phrase over custom codes to avoid transcription errors

Example fix

// before
const secret = codeInput.value; // "nice-owl-atom-lamp\n" on recipient

// after
const secret = codeInput.value.trim();
await sendFiles({ files, secret, settings });
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await sendFiles(opts);
} catch (e) {
  if (/PAKE confirmation failed/.test(e.message)) {
    setCodeError("The code does not match the recipient's code. Re-share it and retry.");
    return; // do NOT retry with the same code automatically
  }
  throw e;
}

Prevention

When it happens

Trigger: Sender and recipient using different secrets for the same room (typo on either side); one party pasting the code with an extra or missing word; auto-correct altering one side's phrase.

Common situations: Manually transcribed codes over voice/chat; trailing whitespace or newline appended on paste on one end only; recipient joining with an old code after the sender regenerated.

Related errors


AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15). Data as JSON: /api/errors/fc31597cb479d85a. Report an issue: GitHub.