Yeachan-Heo/oh-my-codex · error · Error
[native-assets] incomplete lock write
Error message
[native-assets] incomplete lock write
What it means
While creating the publication lock file, a write to the freshly O_EXCL-created file reported fewer bytes than the lock record. This indicates a filesystem-level short write (disk full, quota, or exotic FS), so the lock would be corrupt and is rejected immediately.
Source
Thrown at src/cli/native-assets.ts:575
return { state: 'verified', path: effectiveBinaryPath!, lock: lockDiagnostic };
}
async function acquireCacheLock(binaryPath: string, env: NodeJS.ProcessEnv): Promise<PublicationLock> {
const path = lockPath(binaryPath);
const started = performance.now();
const deadline = started + lockWaitMs(env);
for (;;) {
const token = uuid();
const record = lockRecord(token, binaryPath);
const recordBytes = Buffer.from(record, 'utf8');
try {
const handle = await open(path, constants.O_RDWR | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
try {
const { bytesWritten } = await handle.write(recordBytes, 0, recordBytes.length, 0);
if (bytesWritten !== recordBytes.length) throw new Error('[native-assets] incomplete lock write');
const readback = Buffer.alloc(recordBytes.length);
const { bytesRead } = await handle.read(readback, 0, readback.length, 0);
if (bytesRead !== readback.length || !readback.equals(recordBytes)) throw new Error('[native-assets] lock readback mismatch');
const identity = await handle.stat();
const fileIdentity = { dev: identity.dev, ino: identity.ino, size: identity.size };
if (!identity.isFile() || identity.nlink !== 1) throw new Error('[native-assets] unsafe publication lock');
await reInspectPath(path, fileIdentity, true);
return { path, token, record, identity: fileIdentity };
} finally { await handle.close(); }
} catch (error) {
if (errno(error) !== 'EEXIST') throw error;
if (performance.now() >= deadline) {
const diagnostic = await inspectLock(path, binaryPath) ?? { path, classification: 'metadata-unavailable' as const };
const owner = diagnostic.owner ? ` owner=${JSON.stringify(diagnostic.owner)}` : '';
throw new Error(`[native-assets] publication-lock-timeout: ${path}; elapsed=${Math.round(performance.now() - started)}ms deadline=${lockWaitMs(env)}ms; ${diagnostic.classification}${owner}. Confirm no OMX hydration process is active for this cache key, remove only this named lock manually, then retry.`);
}
View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Free space on the volume hosting the cache root.
- Point the cache root env var at a local, non-network filesystem.
- Re-run hydration once space is available.
Defensive patterns
Strategy: try-catch
Try / catch
try { await hydrateNativeBinary(); } catch (e) { if (/incomplete lock write/.test(String(e))) { /* free disk space, retry */ } throw e; } Prevention
- Monitor disk space where the cache lives
- Use a local disk rather than tmpfs/NFS for caches
- Retry hydration once after freeing space
When it happens
Trigger: acquireCacheLock when handle.write of the lock record returns bytesWritten < record length — ENOSPC conditions, full tmpfs, or flaky network filesystems backing the cache.
Common situations: Docker containers with tiny tmpfs caches; disk-full CI runners; NFS-backed HOME directories.
Related errors
- [native-assets] lock readback mismatch
- [native-assets] unsafe publication lock
- [native-assets] publication-lock-timeout: ${path}; elapsed=$
- [native-assets] temporary checksum verification failed
- Failed to acquire AGENTS.md lock within timeout
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/15d96591c835cf3f.
Report an issue: GitHub.