schollz/croc · error · Error

Recipient did not confirm the croc PAKE handshake

Error message

Recipient did not confirm the croc PAKE handshake

What it means

After the sender posts its PAKE response, the recipient must reply with a 'pake-confirm' message carrying confirmation bytes (b). If the message type differs or b is missing, the handshake confirmation step never happened. This sits between the PAKE exchange and the key-confirmation check, so it fires on message-order or framing problems rather than wrong-passphrase failures.

Source

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

    const salt = randomBytes(PAKE_SALT_SIZE);
    const peerKeys = await wasm().derivePeerKeys(
      finished.key,
      salt,
      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,

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Retry the transfer with both ends on matching croc versions
  2. Ensure the recipient keeps the connection open through the full handshake (no early cancel)
  3. Regenerate the code and start a fresh room
Defensive patterns

Strategy: try-catch

Type guard

function isPakeConfirm(msg) {
  return !!msg && msg.t === "pake-confirm" && msg.b instanceof Uint8Array && msg.b.length > 0;
}

Try / catch

try {
  await sendFiles(opts);
} catch (e) {
  if (/did not confirm/.test(e.message)) { reconnectAndRetryOnce(); return; }
  throw e;
}

Prevention

When it happens

Trigger: The recipient aborting or erroring between its PAKE message and the confirmation; a version that skips or renames 'pake-confirm'; socket desynchronization from earlier partial reads.

Common situations: Recipient closes the tab mid-handshake; recipient on an older protocol without the confirm step; relay delivering frames out of order after a reconnect.

Understand the failure class

Related errors


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