Yeachan-Heo/oh-my-codex · error · Error
[native-assets] cache publication verification failed: ${fin
Error message
[native-assets] cache publication verification failed: ${final.state} What it means
After atomically renaming the binary and sidecar into place, inspectManagedNativeBinary did not report state 'verified' for the published path. Publication is verified end-to-end (existence, digest match vs sidecar); any other state means the final artifact failed its own post-publication inspection.
Source
Thrown at src/cli/native-assets.ts:658
await revalidatePublicationPaths();
if (platform !== 'win32') await chmod(tempBinary, 0o755);
const binary = await readOpenedFile(tempBinary, true, true);
const sidecar = `${binary.digest}\n`;
const handle = await open(tempSidecar, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
try { await handle.writeFile(sidecar, 'utf8'); } finally { await handle.close(); }
if ((await readOpenedFile(tempSidecar, true, false, MAX_SIDECAR_BYTES)).text !== sidecar) throw new Error('[native-assets] temporary checksum verification failed');
await revalidatePublicationPaths();
await quarantineInvalid(destination);
await revalidatePublicationPaths();
await quarantineInvalid(sidecarPath(destination));
await revalidatePublicationPaths();
await rename(tempBinary, destination);
await revalidatePublicationPaths();
await rename(tempSidecar, sidecarPath(destination));
await revalidatePublicationPaths();
const final = await inspectManagedNativeBinary(destination, env);
await revalidatePublicationPaths();
if (final.state !== 'verified') throw new Error(`[native-assets] cache publication verification failed: ${final.state}`);
return final.path;
} catch (error) {
primaryError = error;
throw error;
} finally {
const cleanupFailures: string[] = [];
try { await revalidatePublicationPaths(); } catch (error) {
cleanupFailures.push(`revalidate publication paths: ${error instanceof Error ? error.message : String(error)}`);
}
for (const temporary of [tempBinary, tempSidecar]) {
try { await rm(temporary, { force: true }); } catch (error) {
cleanupFailures.push(`remove ${temporary}: ${error instanceof Error ? error.message : String(error)}`);
}
}
const lockCleanup = await releaseCacheLock(lock);
if (lockCleanup) cleanupFailures.push(`${lockCleanup.state}: publication lock was retained`);
if (cleanupFailures.length > 0) {
const evidence = `[native-assets] cleanup evidence: ${cleanupFailures.join('; ')}`;View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Stop concurrent cache writers/pruners, clear the specific cache entry, retry once.
- Add cache directory exclusions to antivirus/sync tooling.
- Serialize installs or pre-hydrate caches to avoid post-publication races.
Defensive patterns
Strategy: retry
Try / catch
try { await hydrateNativeBinary(); } catch (e) { if (/cache publication verification failed/.test(String(e))) { /* stop other cache writers, clear entry, retry once */ } throw e; } Prevention
- Serialize cache writes across processes
- Exclude published binaries from antivirus quarantine
- Pre-hydrate caches to eliminate runtime publication
When it happens
Trigger: publishManagedNativeBinary when the post-rename inspection returns e.g. 'digest-mismatch', 'missing-sidecar', or 'stale' — caused by tampering, filesystem races, or an external process deleting/altering files immediately after publication.
Common situations: Concurrent cache pruning by another process; antivirus quarantining freshly written executables; multi-process installs racing on the same destination.
Related errors
- [native-assets] cache publication verification failed for ${
- [native-assets] cache path escapes configured root
- [native-assets] cache descendant is unsafe: ${current}
- [native-assets] lock readback mismatch
- [native-assets] unable to create cache root
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/fb73708a3e83f16a.
Report an issue: GitHub.