{"record":{"id":"42c7deefad919b8c","repo":"Yeachan-Heo/oh-my-codex","slug":"manifest-binary-product-mismatch","errorCode":"manifest_binary_product_mismatch","errorMessage":"[native-assets] manifest_binary_product_mismatch: ${asset.binary}","messagePattern":"\\[native-assets\\] manifest_binary_product_mismatch: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/native-assets/policy.ts","lineNumber":161,"sourceCode":"    const requiredStrings: Array<keyof NativeReleaseAssetPolicyInput> = [\n      'product', 'platform', 'arch', 'target', 'archive', 'binary', 'binary_path', 'sha256', 'download_url',\n    ];\n    if (requiredStrings.some((field) => !requiredString(asset[field]))) {\n      throw policyError('manifest_invalid_asset', asset.archive || 'unknown');\n    }\n    const assetSize = asset.size;\n    if (!/^[a-f0-9]{64}$/.test(asset.sha256) || assetSize === undefined || !Number.isSafeInteger(assetSize) || assetSize <= 0) {\n      throw policyError('manifest_invalid_integrity', asset.archive);\n    }\n    const mapping = nativeTargetMapping(asset.target);\n    if (!mapping || mapping.platform !== asset.platform || mapping.arch !== asset.arch\n      || (mapping.platform === 'linux' ? asset.libc !== mapping.libc : asset.libc !== undefined)) {\n      throw policyError('manifest_target_mismatch', asset.target || asset.archive);\n    }\n    const expectedBinary = nativeProductBinaryName(asset.product);\n    const expectedBinaryPath = nativeProductBinaryPath(asset.product, asset.platform);\n    if (!expectedBinary || !expectedBinaryPath || asset.binary !== expectedBinary) {\n      throw policyError('manifest_binary_product_mismatch', asset.binary);\n    }\n\n    const binaryPath = normalizeNativeArchivePath(asset.binary_path, 'file');\n    if (binaryPath !== asset.binary_path || binaryPath.split('/').at(-1) !== expectedBinaryPath) {\n      throw policyError('manifest_binary_basename_mismatch', asset.binary_path);\n    }\n\n    const key = nativeReleaseAssetLogicalKey(asset);\n    if (logicalKeys.has(key)) throw policyError('manifest_duplicate_logical_key', asset.archive);\n    logicalKeys.add(key);\n    const basename = nativeReleaseAssetBasename(asset);\n    if (asset.archive !== basename || !nativeArchiveSuffix(basename)) {\n      throw policyError('manifest_archive_invalid', asset.archive);\n    }\n    if (archiveHintMismatch(asset, basename)) throw policyError('manifest_archive_hint_mismatch', basename);\n    if (basenames.has(basename)) throw policyError('manifest_duplicate_archive_basename', basename);\n    basenames.add(basename);\n    let downloadUrl: URL;","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/native-assets/policy.ts#L143-L179","documentation":"During validation of a native release manifest, the declared asset binary name does not match the canonical binary name for the asset's product/platform. The policy module computes the expected binary via nativeProductBinaryName/nativeProductBinaryPath and rejects any mismatch to guarantee every archive ships the correct executable.","triggerScenarios":"Calling loadNativeReleaseManifest (or validateNativeReleaseManifest directly) with a manifest whose asset.binary differs from nativeProductBinaryName(asset.product), or where the product/platform combination has no known binary path.","commonSituations":"Manifest hand-edited or generated by a newer/older toolchain with renamed binaries (e.g. product renamed, platform added), or a typo in the asset's product or binary field.","solutions":["Check asset.product and asset.platform values are valid supported combinations","Set asset.binary to exactly nativeProductBinaryName(asset.product) output","Regenerate the manifest with the bundled generator instead of editing by hand","If introducing a new product, update nativeProductBinaryName/nativeProductBinaryPath in policy.ts first"],"exampleFix":"// before\n{ product: 'omxd', platform: 'linux-x64', binary: 'omx-daemon' }\n// after\n{ product: 'omxd', platform: 'linux-x64', binary: 'omxd' }","handlingStrategy":"validation","validationCode":"import { nativeProductBinaryName, nativeProductBinaryPath } from './policy';\nconst ok = asset.binary === nativeProductBinaryName(asset.product)\n  && !!nativeProductBinaryPath(asset.product, asset.platform);","typeGuard":"function isValidAssetBinary(a: NativeAsset): boolean {\n  return a.binary === nativeProductBinaryName(a.product)\n    && !!nativeProductBinaryPath(a.product, a.platform);\n}","tryCatchPattern":"try { loadNativeReleaseManifest(m); } catch (e) { if (String(e).includes('manifest_binary_product_mismatch')) fixBinaryFields(m); else throw e; }","preventionTips":["Generate manifests with the official generator","Add schema tests that run validateNativeReleaseManifest on fixture manifests"],"tags":["native-assets","manifest","validation"],"backgroundTag":"manifest-validation-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}