{"record":{"id":"4eb4cdf81d4be2ac","repo":"schollz/croc","slug":"stored-transfer-exceeds-the-settings-maxtransfer","errorCode":null,"errorMessage":"Stored transfer exceeds the ${settings.maxTransferBytes} byte limit","messagePattern":"Stored transfer exceeds the (.+?) byte limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"web/src/protocol/stored.ts","lineNumber":301,"sourceCode":"    return await engine.sha256Final(handle);\n  } finally {\n    reader.releaseLock();\n  }\n}\n\nexport async function prepareStoredFiles(\n  selected: File[],\n  settings: StoredSettings,\n  callbacks: { onStatus?(status: string): void } = {},\n  signal?: AbortSignal,\n) {\n  if (selected.length === 0) throw new Error(\"Choose at least one file\");\n  if (selected.length > settings.maxFiles) {\n    throw new Error(`Stored transfers can contain at most ${settings.maxFiles} files`);\n  }\n  const total = selected.reduce((sum, file) => sum + file.size, 0);\n  if (!Number.isSafeInteger(total) || total > settings.maxTransferBytes) {\n    throw new Error(`Stored transfer exceeds the ${settings.maxTransferBytes} byte limit`);\n  }\n  const names = new Set<string>();\n  const prepared: StoredPreparedFile[] = [];\n  let firstChunk = 0;\n  for (let index = 0; index < selected.length; index += 1) {\n    const file = selected[index];\n    const name = normalizeOutgoingFileName(file.name);\n    if (names.has(name)) throw new Error(`Duplicate filename: ${name}`);\n    names.add(name);\n    callbacks.onStatus?.(`Hashing ${index + 1}/${selected.length}: ${name}`);\n    const chunkCount = Math.ceil(file.size / storedChunkSize);\n    prepared.push({\n      file,\n      name,\n      size: file.size,\n      hash: new Uint8Array(),\n      sha256: await sha256Blob(file, signal),\n      modified: new Date(file.lastModified).toISOString(),","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/schollz/croc/blob/e25f1bdc04f07f094d50b0a1bf67e2563944b57a/web/src/protocol/stored.ts#L283-L319","documentation":"prepareStoredFiles() sums all selected file sizes and rejects the batch if the total is not a safe integer or exceeds settings.maxTransferBytes. Storage reservations are sized up front, so oversize batches are stopped before any hashing work is done.","triggerScenarios":"Sum of file.size over maxTransferBytes (e.g., 2 GB selected against a 1 GB cap), or a pathological selection whose total overflows 2^53 (not realistic in browsers, hence the Number.isSafeInteger belt-and-braces).","commonSituations":"Selecting large media archives; settings served from the server with a lower maxTransferBytes than users expect; disk-size confusion between GB and GiB when the cap is expressed in plain bytes.","solutions":["Reduce the selection or split into several stored transfers under the byte limit","Pre-compute the total in the UI and show remaining allowance before submit","Verify the maxTransferBytes value the client actually received from settings — it may be lower than the server's real capacity"],"exampleFix":"// before\nconst prepared = await prepareStoredFiles(selected, settings);\n\n// after\nconst total = selected.reduce((s, f) => s + f.size, 0);\nif (total > settings.maxTransferBytes) { alert(\"Transfer too large; remove some files\"); return; }\nconst prepared = await prepareStoredFiles(selected, settings);","handlingStrategy":"validation","validationCode":"const total = selected.reduce((sum, f) => sum + f.size, 0);\nif (!Number.isSafeInteger(total) || total > settings.maxTransferBytes) { showError(\"Selection exceeds the stored-transfer size limit\"); return; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Sum file sizes live in the UI and compare against maxTransferBytes before submit","Display the limit in human-readable units so users understand what fits"],"tags":["validation","limits","size","stored-transfer"],"backgroundTag":null,"analyzedSha":"e25f1bdc04f07f094d50b0a1bf67e2563944b57a","analyzedAt":"2026-08-15T12:53:39.096Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}