{"record":{"id":"aecd62c308c613e4","repo":"JuliusBrussee/caveman","slug":"binary-download-failed-error-message","errorCode":null,"errorMessage":"binary download failed: ${error.message}","messagePattern":"binary download failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/shared/binary-installer/installer.mjs","lineNumber":92,"sourceCode":"export function binaryInstallFilename(name, os = process.platform) {\n  return os === \"win32\" ? `${name}.exe` : name;\n}\n\nfunction timeoutMs() {\n  const raw = process.env.CAVE_SETUP_TIMEOUT ?? \"300\";\n  const seconds = Number(raw);\n  if (!Number.isInteger(seconds) || seconds <= 0) {\n    throw new Error(`CAVE_SETUP_TIMEOUT must be a positive integer (got ${JSON.stringify(raw)})`);\n  }\n  return seconds * 1000;\n}\n\nasync function asset(url, timeout) {\n  let response;\n  try {\n    response = await fetch(url, { signal: AbortSignal.timeout(timeout) });\n  } catch (error) {\n    throw new Error(`binary download failed: ${error.message}`);\n  }\n  if (!response.ok) throw new Error(`binary download failed: HTTP ${response.status}`);\n  return response;\n}\n\nfunction signedDigest(checksums, bundleRaw) {\n  try {\n    const bundle = JSON.parse(bundleRaw);\n    if (bundle.mediaType !== \"application/vnd.dev.sigstore.bundle.v0.3+json\") return false;\n    if (bundle.messageSignature?.messageDigest?.algorithm !== \"SHA2_256\") return false;\n    const digest = createHash(\"sha256\").update(checksums).digest();\n    const bundled = Buffer.from(bundle.messageSignature.messageDigest.digest, \"base64\");\n    if (digest.length !== bundled.length || !digest.equals(bundled)) return false;\n    return verify(\n      \"sha256\",\n      Buffer.from(checksums),\n      createPublicKey(BINARY_SIGNING_PUBKEY),\n      Buffer.from(bundle.messageSignature.signature, \"base64\"),","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/shared/binary-installer/installer.mjs#L74-L110","documentation":"`asset` wraps the installer's fetch of a binary/checksum URL. Any network- or abort-level failure of fetch (DNS failure, connection refused/reset, TLS error, or the AbortSignal.timeout firing) is rethrown as `binary download failed: <original message>`, preserving the cause's message.","triggerScenarios":"fetch rejects: no network/DNS, unreachable or firewalled host, proxy issues, TLS interception, or the request exceeding the timeout passed to asset (AbortSignal.timeout aborts).","commonSituations":"Corporate proxy blocking the download host; GitHub Releases rate-limit or outage; air-gapped CI with no egress; slow link where the setup timeout (CAVE_SETUP_TIMEOUT) expires mid-download.","solutions":["Check basic egress first: curl -I the URL from the same machine to see the underlying cause","Configure HTTPS_PROXY/HTTP_PROXY if the environment requires a proxy for outbound fetch","Raise CAVE_SETUP_TIMEOUT so AbortSignal.timeout doesn't abort slow downloads","Retry the install (transient network/DNS failures) or pre-download the binary and install it manually"],"exampleFix":"// before\n// installer aborts on slow link: binary download failed: The operation was aborted due to timeout\n// after\nCAVE_SETUP_TIMEOUT=900 npx installer","handlingStrategy":"retry","validationCode":"// probe egress before install\nconst probe = await fetch(\"https://github.com\", { method: \"HEAD\", signal: AbortSignal.timeout(5000) }).catch(() => null);\nif (!probe) throw new Error(\"no outbound network access; configure proxy or vendor the binary\");","typeGuard":null,"tryCatchPattern":"async function withRetry(fn, n = 3) {\n  let last;\n  for (let i = 0; i < n; i++) {\n    try { return await fn(); }\n    catch (e) {\n      if (!String(e.message).startsWith(\"binary download failed:\")) throw e;\n      last = e;\n      await new Promise(r => setTimeout(r, 2 ** i * 1000));\n    }\n  }\n  throw last;\n}","preventionTips":["Set HTTPS_PROXY/HTTP_PROXY where egress requires a proxy","Raise CAVE_SETUP_TIMEOUT for slow links","Pre-download binaries and cache them in CI between runs","Retry transient failures with backoff; surface the wrapped cause message for diagnosis"],"tags":["network","download","fetch"],"backgroundTag":"http-request-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}