{"record":{"id":"dbb3c600f3eba527","repo":"schollz/croc","slug":"hash-algorithm-info-hashalgorithm-is-not-supp","errorCode":null,"errorMessage":"Hash algorithm \"${info.HashAlgorithm}\" is not supported","messagePattern":"Hash algorithm \"(.+?)\" is not supported","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/protocol/metadata.ts","lineNumber":66,"sourceCode":"export function normalizeOutgoingFileName(value: string) {\n  // Go's unicode.IsPrint accepts ASCII space but rejects the other Unicode\n  // separator characters commonly inserted into filenames by macOS.\n  const compatible = value.replace(/\\p{Z}+/gu, \" \");\n  return normalizeFilePath(\".\", compatible).name;\n}\n\nfunction finiteSize(file: WireFileInfo) {\n  const size = file.s ?? 0;\n  if (!Number.isSafeInteger(size) || size < 0) {\n    throw new Error(`Invalid file size for ${file.n ?? \"unnamed file\"}`);\n  }\n  return size;\n}\n\nexport 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,","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/schollz/croc/blob/e25f1bdc04f07f094d50b0a1bf67e2563944b57a/web/src/protocol/metadata.ts#L48-L84","documentation":"validateSenderInfo() accepts only the xxhash algorithm. If the offer's HashAlgorithm field is present and set to anything else (e.g. 'sha256', 'md5'), the client cannot verify chunk integrity because its wasm pipeline only implements xxhash, so the transfer is refused before any data flows.","triggerScenarios":"A croc build or fork that negotiates a non-xxhash HashAlgorithm sends an offer to this client; or hand-crafted SenderInfoWire with HashAlgorithm: 'sha256'. An absent or 'xxhash' value passes.","commonSituations":"Peer running a modified/newer croc that switched the default hash algorithm; forked protocol variants; test fixtures copied from a different croc version; security scanners checking the strictness of algorithm negotiation.","solutions":["Have the sender use a croc version whose HashAlgorithm is xxhash (the stock croc default).","If a custom algorithm is mandatory for your deployment, implement it in the wasm verification pipeline first, then widen the check in validateSenderInfo.","As a receiver, catch this error and tell the peer to update/downgrade to a compatible croc build."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"function isSupportedHash(info: SenderInfoWire): boolean {\n  return !info.HashAlgorithm || info.HashAlgorithm === \"xxhash\";\n}","typeGuard":"function hasCompatibleHash(info: SenderInfoWire): info is SenderInfoWire & { HashAlgorithm?: \"xxhash\" } {\n  return !info.HashAlgorithm || info.HashAlgorithm === \"xxhash\";\n}","tryCatchPattern":"try {\n  const offer = validateSenderInfo(info);\n} catch (error) {\n  if (error instanceof Error && /Hash algorithm/.test(error.message)) {\n    notifyUser(\"sender uses an unsupported hash; ask them to use stock croc (xxhash)\");\n    return;\n  }\n  throw error;\n}","preventionTips":["Use stock croc builds whose HashAlgorithm is xxhash or absent.","If you must support another algorithm, implement it in the wasm verifier before widening the check.","Include HashAlgorithm in interop test matrices to catch version drift early."],"tags":["protocol","hash","compatibility","metadata"],"backgroundTag":null,"analyzedSha":"e25f1bdc04f07f094d50b0a1bf67e2563944b57a","analyzedAt":"2026-08-15T12:53:39.096Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}