can1357/oh-my-pi · critical · Error

Downloaded binary digest mismatch: expected ${options.expect

Error message

Downloaded binary digest mismatch: expected ${options.expectedDigest}, received ${digest}

What it means

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.

Source

Thrown at packages/coding-agent/src/cli/update-cli.ts:340

					new Error(
						`Downloaded binary size mismatch: expected ${options.expectedSize} bytes, received at least ${size}`,
					),
				);
				return;
			}
			hash.update(chunk);
			callback(null, chunk);
		},
	});

	try {
		await pipeline(response.body, verifier, fs.createWriteStream(options.targetPath, { mode: 0o600 }));
		const digest = `sha256:${hash.digest("hex")}`;
		if (size !== options.expectedSize) {
			throw new Error(`Downloaded binary size mismatch: expected ${options.expectedSize} bytes, received ${size}`);
		}
		if (digest !== options.expectedDigest) {
			throw new Error(`Downloaded binary digest mismatch: expected ${options.expectedDigest}, received ${digest}`);
		}
		await fs.promises.chmod(options.targetPath, 0o755);
	} catch (err) {
		await unlinkIfExists(options.targetPath);
		if (isTimeoutError(err)) {
			throw new Error("Timed out downloading release binary after 15 minutes", { cause: err });
		}
		if (isUnsupportedProxyError(err)) throw new Error(unsupportedProxyMessage(), { cause: err });
		throw err;
	}
}

/** Result from running the installed binary and parsing its reported version. */
export interface InstalledVersionVerification {
	ok: boolean;
	actual?: string;
	path?: string;
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry the update once — a single transient corruption will pass on re-download.
  2. If it mismatches again, verify independently: download the asset manually and compare `sha256sum` against the digest in the release notes/manifest.
  3. Disable any TLS-intercepting proxy/VPN and retry over a clean path.
  4. If the mismatch persists on a clean connection, treat the channel as compromised and report it to the project — do not bypass the check.

Example fix

// before
$ omp update
// Error: Downloaded binary digest mismatch: expected sha256:abc123..., received sha256:def456...
// after: verify manually then retry
$ sha256sum omp-$(uname -s)-$(uname -m).zip && omp update
Defensive patterns

Strategy: retry

Validate before calling

// fetch expected digest from the release manifest yourself and confirm the release was not re-published
const rel = await fetch("https://api.github.com/repos/<owner>/<repo>/releases/latest").then(r => r.json());
if (new Date(rel.published_at) < new Date(Date.now() - 7 * 864e5) === false && rel.draft) throw new Error("Release in flux; retry later");

Type guard

function isDigestMismatch(err: unknown): boolean {
  return err instanceof Error && err.message.includes("Downloaded binary digest mismatch");
}

Try / catch

try {
  await runUpdate();
} catch (err) {
  if (isDigestMismatch(err)) {
    // retry once; on second failure treat channel as compromised — verify sha256sum manually against release notes
    return runUpdate();
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/6828d7ce2706421a. Report an issue: GitHub.