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.

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)

Solutions

  1. Give each asset a unique archive basename encoding its target
  2. Re-check for accidental duplicate rows
  3. 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

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


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/1f3f0a8c192faf29. Report an issue: GitHub.