Yeachan-Heo/oh-my-codex · error
manifest_duplicate_archive_basename
manifest_duplicate_archive_basename
Error message
[native-assets] manifest_duplicate_archive_basename: ${basename} What it means
Two different logical assets share the same archive basename, which would collide on disk when downloading or extracting. The validator tracks every basename and rejects repeats.
Solutions
- Give each asset a unique archive basename encoding its target
- Re-check for accidental duplicate rows
- Regenerate names from the asset fields so they cannot collide
Example fix
// before
[..., {archive:'omxd-linux-x64.tar.zst'}, {archive:'omxd-linux-x64.tar.zst'}]
// after
[..., {archive:'omxd-linux-x64.tar.zst'}, {archive:'omxd-linux-arm64.tar.zst'}] Defensive patterns
Strategy: validation
Validate before calling
const names = new Set<string>();
const ok = assets.every((a) => { const b = nativeReleaseAssetBasename(a); if (names.has(b)) return false; names.add(b); return true; }); Prevention
- Derive archive names from asset fields so collisions are impossible
When it happens
Trigger: Two entries with different logical keys but the identical archive filename, e.g. both ending in 'omxd-linux-x64.tar.zst'.
Common situations: Copy-paste when adding an asset without updating the filename, or a generator bug emitting the same name for multiple targets.
Related errors
- manifest_archive_hint_mismatch
- manifest_archive_invalid
- manifest_binary_basename_mismatch
- manifest_binary_product_mismatch
- manifest_duplicate_logical_key
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/1f3f0a8c192faf29.
Report an issue: GitHub.
Appendix: source
Thrown at src/native-assets/policy.ts:177
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)