Yeachan-Heo/oh-my-codex · error
manifest_archive_invalid
manifest_archive_invalid
Error message
[native-assets] manifest_archive_invalid: ${asset.archive} What it means
The asset's archive field must equal its canonical basename (from nativeReleaseAssetBasename) and end with a recognized archive suffix (checked by nativeArchiveSuffix). This prevents directory components and unsupported archive formats.
Source
Thrown at src/native-assets/policy.ts:174
throw policyError('manifest_target_mismatch', asset.target || asset.archive);
}
const expectedBinary = nativeProductBinaryName(asset.product);
const expectedBinaryPath = nativeProductBinaryPath(asset.product, asset.platform);
if (!expectedBinary || !expectedBinaryPath || asset.binary !== expectedBinary) {
throw policyError('manifest_binary_product_mismatch', asset.binary);
}
const binaryPath = normalizeNativeArchivePath(asset.binary_path, 'file');
if (binaryPath !== asset.binary_path || binaryPath.split('/').at(-1) !== expectedBinaryPath) {
throw policyError('manifest_binary_basename_mismatch', asset.binary_path);
}
const key = nativeReleaseAssetLogicalKey(asset);
if (logicalKeys.has(key)) throw policyError('manifest_duplicate_logical_key', asset.archive);
logicalKeys.add(key);
const basename = nativeReleaseAssetBasename(asset);
if (asset.archive !== basename || !nativeArchiveSuffix(basename)) {
throw policyError('manifest_archive_invalid', asset.archive);
}
if (archiveHintMismatch(asset, basename)) throw policyError('manifest_archive_hint_mismatch', basename);
if (basenames.has(basename)) throw policyError('manifest_duplicate_archive_basename', basename);
basenames.add(basename);
let downloadUrl: URL;
try {
downloadUrl = new URL(asset.download_url);
} catch {
throw policyError('manifest_invalid_url', asset.download_url);
}
if ((downloadUrl.protocol !== 'https:' && downloadUrl.protocol !== 'http:')
|| downloadUrl.pathname.split('/').at(-1) !== basename) {
throw policyError('manifest_url_basename_mismatch', asset.download_url);
}
}
}
View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Set asset.archive to the exact basename with a supported suffix (e.g. .tar.zst)
- Verify nativeReleaseAssetBasename(asset) reproduces the same string
- Avoid directory separators in the archive field
Example fix
// before "archive": "dist/omxd-linux-x64.tar.gz" // after "archive": "omxd-linux-x64.tar.zst"
Defensive patterns
Strategy: validation
Validate before calling
const ok = assets.every((a) => a.archive === nativeReleaseAssetBasename(a) && !!nativeArchiveSuffix(a.archive));
Type guard
function hasValidArchive(a: NativeAsset): boolean {
return a.archive === nativeReleaseAssetBasename(a) && !!nativeArchiveSuffix(a.archive);
} Prevention
- Keep archive fields to bare filenames with supported suffixes
- Check nativeArchiveSuffix's supported list before renaming archives
When it happens
Trigger: asset.archive contains a path ('dist/foo.tar.zst'), has no recognized extension, or disagrees with the basename reconstructed from the asset's fields.
Common situations: Using .tar.gz when only .tar.zst is supported, or leaking a full relative path into the archive name field.
Related errors
- [native-assets] failed to fetch native release manifest (${r
- [native-assets] manifest version mismatch: expected ${versio
- manifest_binary_product_mismatch
- manifest_binary_basename_mismatch
- manifest_duplicate_logical_key
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/d0b84c4b1e822233.
Report an issue: GitHub.