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
- Read the embedded message.m if present: it carries the recipient's actual failure text
- On the recipient, free disk/quota space and grant write access, then retry the transfer
- 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
- On the recipient, check available disk/quota before accepting large transfers
- Propagate message.m to the UI so the recipient's reason is visible to the sender
- Handle recipient cancellation gracefully instead of surfacing a generic failure
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.