{"record":{"id":"dbcf58ada559a228","repo":"schollz/croc","slug":"transfer-size-is-too-large","errorCode":null,"errorMessage":"Transfer size is too large","messagePattern":"Transfer size is too large","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/protocol/metadata.ts","lineNumber":81,"sourceCode":"export function validateSenderInfo(info: SenderInfoWire): TransferOffer {\n  if (info.SendingText) throw new Error(\"Text transfers are not supported yet\");\n  if (info.HashAlgorithm && info.HashAlgorithm !== \"xxhash\") {\n    throw new Error(`Hash algorithm \"${info.HashAlgorithm}\" is not supported`);\n  }\n\n  const destinations = new Set<string>();\n  const files: OfferedFile[] = [];\n  let totalSize = 0;\n  for (const wire of info.FilesToTransfer ?? []) {\n    if (wire.sy) throw new Error(\"Symlink transfers are not supported in the browser\");\n    const normalized = normalizeFilePath(wire.fr ?? \".\", wire.n ?? \"\");\n    if (destinations.has(normalized.path)) {\n      throw new Error(`Duplicate destination path: ${normalized.path}`);\n    }\n    destinations.add(normalized.path);\n    const size = finiteSize(wire);\n    totalSize += size;\n    if (!Number.isSafeInteger(totalSize)) throw new Error(\"Transfer size is too large\");\n    files.push({\n      ...normalized,\n      size,\n      hash: wire.h ? base64ToBytes(wire.h) : new Uint8Array(),\n      modified: wire.m,\n      mode: wire.md,\n    });\n  }\n\n  const emptyFolders: string[] = [];\n  for (const wire of info.EmptyFoldersToTransfer ?? []) {\n    const folder = normalizeFolder(wire.fr ?? \".\");\n    if (destinations.has(folder)) {\n      throw new Error(`Duplicate destination path: ${folder}`);\n    }\n    destinations.add(folder);\n    emptyFolders.push(folder);\n  }","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/schollz/croc/blob/e25f1bdc04f07f094d50b0a1bf67e2563944b57a/web/src/protocol/metadata.ts#L63-L99","documentation":"validateSenderInfo() accumulates the total transfer size across all offered files and throws once the running sum stops being a safe integer (> 2^53-1 ≈ 9 PB). Beyond that bound, byte offsets and progress arithmetic in JavaScript lose precision, so the transfer cannot be tracked correctly.","triggerScenarios":"An offer whose summed file sizes exceed Number.MAX_SAFE_INTEGER — either a genuinely enormous multi-file transfer or a hostile peer declaring huge per-file sizes that individually pass finiteSize (each ≤ 2^53-1) but overflow in aggregate.","commonSituations":"Bulk-archival sends of petabyte-scale datasets; hostile metadata probing numeric limits; fuzzed offers with maximal 's' values; feeds that were meant to be size-limited but were not.","solutions":["Split the transfer into several sends, each comfortably below 2^53 bytes total.","If you operate a receiving service, cap accepted totalSize (e.g. 1 TB) before invoking validateSenderInfo-style logic so users get an actionable limit error.","Never rewrite the guard to allow unsafe sums — downstream offset math will silently corrupt."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const MAX_TOTAL = Number.MAX_SAFE_INTEGER; // ~9 PB hard ceiling\nfunction totalWithinLimit(info: SenderInfoWire, cap = MAX_TOTAL): boolean {\n  let sum = 0;\n  for (const f of info.FilesToTransfer ?? []) {\n    sum += f.s ?? 0;\n    if (!(Number.isSafeInteger(sum)) || sum > cap) return false;\n  }\n  return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const offer = validateSenderInfo(info);\n} catch (error) {\n  if (error instanceof Error && error.message === \"Transfer size is too large\") {\n    notifyUser(\"transfer exceeds browser-safe total size; split into multiple sends\");\n    return;\n  }\n  throw error;\n}","preventionTips":["Split very large multi-file sends so each transfer's total stays far below 2^53 bytes.","Apply your own (lower) total-size cap in receiving services for actionable errors.","Do not weaken the safe-integer check; downstream offset math depends on it."],"tags":["validation","numeric-limits","metadata"],"backgroundTag":null,"analyzedSha":"e25f1bdc04f07f094d50b0a1bf67e2563944b57a","analyzedAt":"2026-08-15T12:53:39.096Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}