schollz/croc · warning · Error

Text transfers are not supported yet

Error message

Text transfers are not supported yet

What it means

validateSenderInfo() rejects any offer with a truthy SendingText field. The browser client implements file transfer only; croc's text-message mode ('croc send --text') has no receiving UI/sink here, so such offers are refused upfront rather than half-processed.

Source

Thrown at web/src/protocol/metadata.ts:64

}

export function normalizeOutgoingFileName(value: string) {
  // Go's unicode.IsPrint accepts ASCII space but rejects the other Unicode
  // separator characters commonly inserted into filenames by macOS.
  const compatible = value.replace(/\p{Z}+/gu, " ");
  return normalizeFilePath(".", compatible).name;
}

function finiteSize(file: WireFileInfo) {
  const size = file.s ?? 0;
  if (!Number.isSafeInteger(size) || size < 0) {
    throw new Error(`Invalid file size for ${file.n ?? "unnamed file"}`);
  }
  return size;
}

export function validateSenderInfo(info: SenderInfoWire): TransferOffer {
  if (info.SendingText) throw new Error("Text transfers are not supported yet");
  if (info.HashAlgorithm && info.HashAlgorithm !== "xxhash") {
    throw new Error(`Hash algorithm "${info.HashAlgorithm}" is not supported`);
  }

  const destinations = new Set<string>();
  const files: OfferedFile[] = [];
  let totalSize = 0;
  for (const wire of info.FilesToTransfer ?? []) {
    if (wire.sy) throw new Error("Symlink transfers are not supported in the browser");
    const normalized = normalizeFilePath(wire.fr ?? ".", wire.n ?? "");
    if (destinations.has(normalized.path)) {
      throw new Error(`Duplicate destination path: ${normalized.path}`);
    }
    destinations.add(normalized.path);
    const size = finiteSize(wire);
    totalSize += size;
    if (!Number.isSafeInteger(totalSize)) throw new Error("Transfer size is too large");
    files.push({

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. On the sender, re-send as a file: write the text to a file or use croc's file mode so SendingText is unset.
  2. As the web receiver, surface a clear 'text transfers are unsupported' message and ask the peer to resend as a file.
  3. If building a client on top, check SendingText before accepting and guide the user to file mode.

Example fix

# before (sender)
croc send --text "hello"
# after (sender)
echo "hello" > note.txt && croroc send note.txt
Defensive patterns

Strategy: try-catch

Validate before calling

function isFileOnlyOffer(info: SenderInfoWire): boolean {
  return !info.SendingText;
}
if (!isFileOnlyOffer(info)) {
  notifyUser("ask sender to resend as a file — text mode is unsupported");
}

Try / catch

try {
  const offer = validateSenderInfo(info);
} catch (error) {
  if (error instanceof Error && error.message === "Text transfers are not supported yet") {
    showNotice("The peer sent a text message; ask them to send it as a file.");
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: A peer runs 'croc send --text "..."' and the receiver is this browser client; validateSenderInfo sees info.SendingText truthy and throws before inspecting files.

Common situations: Sender accidentally in text mode (clipboard paste auto-detection in croc CLI); mixed senders where one user tries to send a quick note alongside a transfer; CI tests exercising text mode against the web receiver.

Related errors


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