can1357/oh-my-pi · error · Error

Downloaded binary size mismatch: expected ${options.expected

Error message

Downloaded binary size mismatch: expected ${options.expectedSize} bytes, received ${size}

What it means

Thrown by downloadVerifiedBinary after the download pipeline completes when the number of bytes streamed to the target file does not equal options.expectedSize from the release manifest. This is an integrity check guarding against truncated or padded downloads before the binary is trusted and chmod'ed executable. The partially-written file is deleted by the surrounding catch before this point via unlinkIfExists in the outer handler.

Source

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

			size += chunk.byteLength;
			if (size > options.expectedSize) {
				callback(
					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;

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-run `omp update` — a complete retry re-downloads and re-verifies from scratch.
  2. Check free disk space on the target filesystem (`df -h`) and retry.
  3. Bypass proxies/VPNs that may truncate long transfers and retry.
  4. If it reproduces on a good connection, report the release manifest/asset size mismatch to the project maintainers.

Example fix

// before: disk full causes truncated download
$ omp update
// Error: Downloaded binary size mismatch: expected 48231424 bytes, received 12058368
// after: free space, then retry
$ df -h ~/.omp && omp update
Defensive patterns

Strategy: retry

Validate before calling

const stat = await fs.statfs(path.dirname(targetPath)).catch(() => null);
if (stat && stat.bavail * stat.bsize < expectedSize) throw new Error("Insufficient disk space for update download");

Type guard

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

Try / catch

try {
  await runUpdate();
} catch (err) {
  if (isSizeMismatch(err)) {
    // truncated transfer: free disk space / bypass proxy, then retry once
    return runUpdate();
  }
  throw err;
}

Prevention

When it happens

Trigger: The response body ended early (connection closed mid-stream) but the pipeline resolved without an error; a middlebox/proxy truncated the transfer; disk-full silently truncated the write stream; expectedSize from the release manifest disagrees with the actual asset (release re-uploaded with a stale manifest).

Common situations: Unstable Wi-Fi or mobile hotspot dropping the connection near the end of a large binary download; corporate proxies with transfer size limits; a release pipeline that re-published an asset without updating the manifest.

Related errors


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