Yeachan-Heo/oh-my-codex · error

manifest_binary_basename_mismatch

manifest_binary_basename_mismatch

Error message

[native-assets] manifest_binary_basename_mismatch: ${asset.binary_path}

What it means

The asset's binary_path must already be normalized and its basename must equal the canonical binary path segment for the product. This check catches unnormalized paths and misplaced binaries inside the archive layout.

Source

Thrown at src/native-assets/policy.ts:166

    }
    const assetSize = asset.size;
    if (!/^[a-f0-9]{64}$/.test(asset.sha256) || assetSize === undefined || !Number.isSafeInteger(assetSize) || assetSize <= 0) {
      throw policyError('manifest_invalid_integrity', asset.archive);
    }
    const mapping = nativeTargetMapping(asset.target);
    if (!mapping || mapping.platform !== asset.platform || mapping.arch !== asset.arch
      || (mapping.platform === 'linux' ? asset.libc !== mapping.libc : asset.libc !== undefined)) {
      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);
    }

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Normalize the path so normalizeNativeArchivePath is a no-op (forward slashes, no './' or '..')
  2. Ensure the basename equals nativeProductBinaryPath(product, platform)
  3. Regenerate the manifest automatically

Example fix

// before
"binary_path": "./bin/omxd"
// after
"binary_path": "bin/omxd"
Defensive patterns

Strategy: validation

Validate before calling

const p = normalizeNativeArchivePath(asset.binary_path, 'file');
const ok = p === asset.binary_path && p.split('/').at(-1) === nativeProductBinaryPath(asset.product, asset.platform);

Type guard

function hasCanonicalBinaryPath(a: NativeAsset): boolean {
  const p = normalizeNativeArchivePath(a.binary_path, 'file');
  return p === a.binary_path && p.split('/').at(-1) === nativeProductBinaryPath(a.product, a.platform);
}

Prevention

When it happens

Trigger: validateNativeReleaseManifest with asset.binary_path like './bin/tool', 'bin//tool', or whose last path segment differs from nativeProductBinaryPath(asset.product, asset.platform).

Common situations: Relative paths, trailing slashes, double slashes, or a binary stored under a different directory name than the canonical layout.

Related errors


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