schollz/croc · error · Error

This browser cannot stream a file this large. Receive it wit

Error message

This browser cannot stream a file this large. Receive it with the croc CLI instead.

What it means

Thrown by chooseStoredReceiveDestination when the browser has neither showDirectoryPicker (File System Access API) nor streaming-download support (service workers + MessageChannel + secure context), and the largest offered file exceeds 256 MiB. Without streaming, the fallback DownloadDestination buffers the entire file in memory as a Blob, which the code refuses to do for large files.

Source

Thrown at web/src/protocol/storage.ts:379

  ) {
    throw new DOMException("Destination selection cancelled", "AbortError");
  }
  return new DirectoryDestination(directory);
}

export async function chooseStoredReceiveDestination(offer: TransferOffer) {
  if (window.showDirectoryPicker) {
    return chooseReceiveDestination(offer);
  }
  if (supportsStreamingDownloadDestination()) {
    return new StreamingDownloadDestination();
  }
  const largest = offer.files.reduce(
    (maximum, file) => Math.max(maximum, file.size),
    0,
  );
  if (largest > 256 * 1024 * 1024) {
    throw new Error(
      "This browser cannot stream a file this large. Receive it with the croc CLI instead.",
    );
  }
  return new DownloadDestination();
}

export async function verifySink(sink: ReceiveSink, expected: Uint8Array) {
  const actual = await sink.hash();
  if (!bytesEqual(actual, expected)) {
    throw new Error(
      `The sender advertised xxhash ${hex(expected)}, but the received file hashes to ${hex(actual)}`,
    );
  }
}

export async function verifySinkSHA256(
  sink: ReceiveSink,
  expected: Uint8Array,

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Receive with the croc CLI using the CLI token (formatStoredCLIToken) instead of the browser
  2. Serve the web app over HTTPS (or localhost) so supportsStreamingDownloadDestination() becomes true and streaming works
  3. Use a Chromium-based browser where showDirectoryPicker is available regardless of size
  4. Have the sender split the transfer into pieces under 256 MiB
Defensive patterns

Strategy: fallback

Validate before calling

import { supportsStreamingDownloadDestination, supportsDirectoryDestination } from "../protocol/storage";
const canBrowserReceive = (offer: TransferOffer): boolean =>
  supportsDirectoryDestination() ||
  supportsStreamingDownloadDestination() ||
  offer.files.every((f) => f.size <= 256 * 1024 * 1024);

Try / catch

try { return await chooseStoredReceiveDestination(offer); } catch (e) { if (e instanceof Error && e.message.includes("croc CLI")) { showUseCLIPrompt(share); return null; } throw e; }

Prevention

When it happens

Trigger: offer.files max size > 256*1024*1024 AND window.showDirectoryPicker is undefined AND supportsStreamingDownloadDestination() is false (no serviceWorker, no MessageChannel, or insecure context on a non-localhost host).

Common situations: Firefox or Safari receiving a >256 MiB stored transfer; any browser serving the app over plain HTTP from a LAN IP or hostname (not a secure context, so no service worker registration); private-mode windows where service workers are disabled. The remedy is literally in the message: use the croc CLI receiver.

Related errors


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