{"record":{"id":"6828d7ce2706421a","repo":"can1357/oh-my-pi","slug":"downloaded-binary-digest-mismatch-expected-opti","errorCode":null,"errorMessage":"Downloaded binary digest mismatch: expected ${options.expectedDigest}, received ${digest}","messagePattern":"Downloaded binary digest mismatch: expected (.+?), received (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/coding-agent/src/cli/update-cli.ts","lineNumber":340,"sourceCode":"\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`Downloaded binary size mismatch: expected ${options.expectedSize} bytes, received at least ${size}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thash.update(chunk);\n\t\t\tcallback(null, chunk);\n\t\t},\n\t});\n\n\ttry {\n\t\tawait pipeline(response.body, verifier, fs.createWriteStream(options.targetPath, { mode: 0o600 }));\n\t\tconst digest = `sha256:${hash.digest(\"hex\")}`;\n\t\tif (size !== options.expectedSize) {\n\t\t\tthrow new Error(`Downloaded binary size mismatch: expected ${options.expectedSize} bytes, received ${size}`);\n\t\t}\n\t\tif (digest !== options.expectedDigest) {\n\t\t\tthrow new Error(`Downloaded binary digest mismatch: expected ${options.expectedDigest}, received ${digest}`);\n\t\t}\n\t\tawait fs.promises.chmod(options.targetPath, 0o755);\n\t} catch (err) {\n\t\tawait unlinkIfExists(options.targetPath);\n\t\tif (isTimeoutError(err)) {\n\t\t\tthrow new Error(\"Timed out downloading release binary after 15 minutes\", { cause: err });\n\t\t}\n\t\tif (isUnsupportedProxyError(err)) throw new Error(unsupportedProxyMessage(), { cause: err });\n\t\tthrow err;\n\t}\n}\n\n/** Result from running the installed binary and parsing its reported version. */\nexport interface InstalledVersionVerification {\n\tok: boolean;\n\tactual?: string;\n\tpath?: string;\n}","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/cli/update-cli.ts#L322-L358","documentation":"Thrown by downloadVerifiedBinary when the SHA-256 digest computed while streaming the downloaded binary (sha256:${hash.digest(\"hex\")}) does not match options.expectedDigest from the release manifest. This is the final integrity gate: it ensures the executable about to be installed is byte-identical to the one the project published, protecting against corruption and tampering. The target file is removed before the error propagates.","triggerScenarios":"Content was corrupted in transit (bit-flips through a faulty proxy/VPN, CDN cache poisoning) while the size happened to match; the release asset was re-uploaded after the manifest recorded its digest; a man-in-the-middle substituted the payload.","commonSituations":"Downloads through intercepting corporate TLS proxies that re-encode content; comparing against a digest from a previous canary build after the release was rebuilt; repeated mismatch across retries suggests a compromised or stale mirror.","solutions":["Retry the update once — a single transient corruption will pass on re-download.","If it mismatches again, verify independently: download the asset manually and compare `sha256sum` against the digest in the release notes/manifest.","Disable any TLS-intercepting proxy/VPN and retry over a clean path.","If the mismatch persists on a clean connection, treat the channel as compromised and report it to the project — do not bypass the check."],"exampleFix":"// before\n$ omp update\n// Error: Downloaded binary digest mismatch: expected sha256:abc123..., received sha256:def456...\n// after: verify manually then retry\n$ sha256sum omp-$(uname -s)-$(uname -m).zip && omp update","handlingStrategy":"retry","validationCode":"// fetch expected digest from the release manifest yourself and confirm the release was not re-published\nconst rel = await fetch(\"https://api.github.com/repos/<owner>/<repo>/releases/latest\").then(r => r.json());\nif (new Date(rel.published_at) < new Date(Date.now() - 7 * 864e5) === false && rel.draft) throw new Error(\"Release in flux; retry later\");","typeGuard":"function isDigestMismatch(err: unknown): boolean {\n  return err instanceof Error && err.message.includes(\"Downloaded binary digest mismatch\");\n}","tryCatchPattern":"try {\n  await runUpdate();\n} catch (err) {\n  if (isDigestMismatch(err)) {\n    // retry once; on second failure treat channel as compromised — verify sha256sum manually against release notes\n    return runUpdate();\n  }\n  throw err;\n}","preventionTips":["Never bypass digest verification","Disable TLS-intercepting proxies for release downloads","On repeated mismatch, verify manually with sha256sum and report to maintainers"],"tags":["security","integrity","sha256","download","update-cli"],"backgroundTag":"checksum-mismatch","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}