Yeachan-Heo/oh-my-codex · error · Error
[native-assets] downloaded archive size mismatch for ${asset
Error message
[native-assets] downloaded archive size mismatch for ${asset.archive} What it means
The downloaded release archive's on-disk size does not match the size declared in the release manifest. This is the first integrity gate after downloadFile; a size mismatch means a truncated or altered download and the asset is rejected before checksum verification/extraction.
Source
Thrown at src/cli/native-assets.ts:735
const extractedBinaryPath = join(tempRoot, 'native-binary');
try {
for (let index = 0; index < assets.length; index += 1) {
const asset = assets[index]!;
const archivePath = join(tempRoot, asset.archive);
const cachedBinaryPath = resolveCachedNativeBinaryPath(
product,
version,
platform,
arch,
env,
inferNativeAssetLibc(asset),
);
try {
await downloadFile(asset.download_url, archivePath);
const archiveStat = await stat(archivePath);
if (typeof asset.size === 'number' && asset.size > 0 && archiveStat.size !== asset.size) {
throw new Error(`[native-assets] downloaded archive size mismatch for ${asset.archive}`);
}
const digest = await sha256ForFile(archivePath);
if (digest !== asset.sha256) {
throw new Error(`[native-assets] checksum mismatch for ${asset.archive}`);
}
const archiveEntries = await inspectNativeArchive(archivePath);
const archiveBinary = selectNativeArchiveBinary(archiveEntries, asset.binary_path);
await writeSelectedNativeArchiveMember(archivePath, archiveBinary.path, extractedBinaryPath);
const published = await publishManagedNativeBinary(extractedBinaryPath, cachedBinaryPath, platform, env);
if (published) return published;
throw new Error(`[native-assets] cache publication verification failed for ${cachedBinaryPath}`);
} catch (error) {
if (index < assets.length - 1 && isUnavailableArchiveError(error)) {
await rm(archivePath, { force: true });
await rm(extractedBinaryPath, { force: true });
continue;View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Delete the partial archive (the library also cleans on retry) and re-run hydration on a stable network.
- Bypass/fix truncating proxies; verify by curl-ing the asset URL and comparing Content-Length with the manifest.
- If the release itself is bad, report/re-publish the manifest+assets so sizes agree.
Defensive patterns
Strategy: retry
Validate before calling
async function sizeMatches(url: string, expected: number): Promise<boolean> { const r = await fetch(url, { method: 'HEAD' }); return r.ok && Number(r.headers.get('content-length')) === expected; } Try / catch
try { await hydrateNativeBinary(); } catch (e) { if (/archive size mismatch/.test(String(e))) { /* re-download on stable network / check proxy truncation */ } throw e; } Prevention
- Use a stable network for first hydration
- Bypass binary-truncating proxies
- Vendor pre-hydrated caches in CI images
When it happens
Trigger: hydrateNativeBinary downloading an asset whose manifest-listed size is a positive number but stat(archivePath).size differs — truncated transfers through proxies, HTML error pages saved instead of the archive, or a manifest published with stale sizes.
Common situations: Corporate proxies truncating large binaries; mirrors whose assets differ from upstream; releases where the manifest was regenerated without re-uploading assets.
Related errors
- [native-assets] failed to download ${url} (${response.status
- [native-assets] checksum mismatch for ${asset.archive}
- Unknown adapt target: ${target}
- native_agent_canonical_invalid
- invalid auth slot name: use 1-64 letters, numbers, '.', '_'
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/d9da86d8b9a72fbf.
Report an issue: GitHub.