schollz/croc · error · Error

Recipient refused transfer

Error message

Recipient refused transfer

What it means

Inside the sender's transfer loop, the recipient sent an 'error' control message. The error text from the recipient is used if present (message.m), otherwise this default is thrown. It is the recipient's refusal or failure propagated over the encrypted control channel, commonly a disk-space or write-permission failure on the receiving side.

Source

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

      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");
    await sendControl(control, { t: "externalip", m: relay.externalIP }, key);
    await sendControl(control, {
      t: "fileinfo",
      b: textEncoder.encode(JSON.stringify(senderInfo(files))),
    }, key);

    let totalTransferred = 0;
    for (;;) {
      checkAbort(signal);
      const message = await receiveControl(control, key);
      if (message.t === "error") throw new Error(message.m || "Recipient refused transfer");
      if (message.t === "finished") {
        await sendControl(control, { t: "finished" }, key);
        callbacks.onStatus?.("Transfer complete");
        return;
      }
      if (message.t !== "recipientready" || !message.b) {
        throw new Error(`Unexpected peer message: ${message.t}`);
      }

      const request = JSON.parse(
        textDecoder.decode(message.b),
      ) as RemoteFileRequestWire;
      const fileIndex = request.FilesToTransferCurrentNum;
      const prepared = files[fileIndex];
      if (!prepared) throw new Error("Recipient requested an unknown file");
      callbacks.onStatus?.(`Sending ${prepared.name}`);
      const beforeFile = totalTransferred;
      await sendFileData(

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Read the embedded message.m if present: it carries the recipient's actual failure text
  2. On the recipient, free disk/quota space and grant write access, then retry the transfer
  3. If the recipient cancelled, simply restart the transfer when both sides are ready
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await sendFiles(opts);
} catch (e) {
  if (/refused transfer/.test(e.message)) {
    showBanner(e.message); // message.m from the recipient explains why
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Recipient's verifySink or storage write failing (no disk space, permission denied, quota exceeded in the browser); recipient actively cancelling; recipient's wasm reporting a decompression/hash error.

Common situations: Receiving in a browser storage sandbox with exhausted quota; recipient tab losing its FileSystem handle mid-transfer; recipient hits cancel while blocks are in flight.

Related errors


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