schollz/croc · info

Transfer refused

Error message

Transfer refused

What it means

Thrown by receiveStoredTransfer when the user declined: the callbacks.onOffer(inspection.offer) hook returned a falsy destination. This is the library's explicit user-refusal signal, not an infrastructure failure: the receiver saw the file list and chose not to save.

Source

Thrown at web/src/protocol/stored.ts:914

  callbacks: ReceiveCallbacks;
  signal?: AbortSignal;
}) {
  const { inspection, settings, callbacks, signal } = options;

  if (hasVerifiedDownload(inspection.share.id)) {
    const session: StoredReceiveSession = {
      inspection,
      settings,
      callbacks,
      signal,
      claimToken: await claimStored(inspection, settings, signal),
      totalBytes: inspection.offer.totalSize,
    };
    return commitStoredDownload(session);
  }

  const destination = await callbacks.onOffer(inspection.offer);
  if (!destination) throw new Error("Transfer refused");
  const session: StoredReceiveSession = {
    inspection,
    settings,
    callbacks,
    signal,
    claimToken: await claimStored(inspection, settings, signal),
    totalBytes: 0,
  };
  for (
    let fileIndex = 0;
    fileIndex < inspection.manifest.f.length;
    fileIndex += 1
  ) {
    await downloadStoredFile(session, destination, fileIndex);
  }
  rememberVerifiedDownload(inspection.share.id);
  return commitStoredDownload(session);
}

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Catch and branch on the 'Transfer refused' message: treat it as a clean cancel, not an error
  2. Ensure onOffer returns the chosen destination only on explicit acceptance
  3. Exit silently or update UI state to 'declined' on this path

Example fix

// before
try {
  await receiveStoredTransfer({ inspection, settings, callbacks, signal });
} catch {
  showError('Download failed'); // wrong for user cancel
}

// after
try {
  await receiveStoredTransfer({ inspection, settings, callbacks, signal });
} catch (e) {
  if (e instanceof Error && e.message === 'Transfer refused') return; // user declined
  throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try { await receiveStoredTransfer({ inspection, settings, callbacks, signal }); } catch (e) { if (e instanceof Error && e.message === 'Transfer refused') return { declined: true }; throw e; }

Prevention

When it happens

Trigger: Calling receiveStoredTransfer with an onOffer callback that returns undefined/null/false because the user clicked Cancel/Reject (or the callback has no prompt UI and implicitly returns undefined).

Common situations: Generic error handlers showing 'Download failed' when the user merely cancelled; automation wrappers whose onOffer forgets to return a destination path.

Related errors


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