{"record":{"id":"15d96591c835cf3f","repo":"Yeachan-Heo/oh-my-codex","slug":"native-assets-incomplete-lock-write","errorCode":null,"errorMessage":"[native-assets] incomplete lock write","messagePattern":"\\[native-assets\\] incomplete lock write","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/native-assets.ts","lineNumber":575,"sourceCode":"  return { state: 'verified', path: effectiveBinaryPath!, lock: lockDiagnostic };\n}\n\nasync function acquireCacheLock(binaryPath: string, env: NodeJS.ProcessEnv): Promise<PublicationLock> {\n\n  const path = lockPath(binaryPath);\n  const started = performance.now();\n  const deadline = started + lockWaitMs(env);\n\n  for (;;) {\n    const token = uuid();\n    const record = lockRecord(token, binaryPath);\n\n    const recordBytes = Buffer.from(record, 'utf8');\n    try {\n      const handle = await open(path, constants.O_RDWR | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);\n      try {\n        const { bytesWritten } = await handle.write(recordBytes, 0, recordBytes.length, 0);\n        if (bytesWritten !== recordBytes.length) throw new Error('[native-assets] incomplete lock write');\n        const readback = Buffer.alloc(recordBytes.length);\n        const { bytesRead } = await handle.read(readback, 0, readback.length, 0);\n        if (bytesRead !== readback.length || !readback.equals(recordBytes)) throw new Error('[native-assets] lock readback mismatch');\n        const identity = await handle.stat();\n        const fileIdentity = { dev: identity.dev, ino: identity.ino, size: identity.size };\n        if (!identity.isFile() || identity.nlink !== 1) throw new Error('[native-assets] unsafe publication lock');\n        await reInspectPath(path, fileIdentity, true);\n        return { path, token, record, identity: fileIdentity };\n\n      } finally { await handle.close(); }\n    } catch (error) {\n      if (errno(error) !== 'EEXIST') throw error;\n      if (performance.now() >= deadline) {\n        const diagnostic = await inspectLock(path, binaryPath) ?? { path, classification: 'metadata-unavailable' as const };\n        const owner = diagnostic.owner ? ` owner=${JSON.stringify(diagnostic.owner)}` : '';\n        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.`);\n      }\n","sourceCodeStart":557,"sourceCodeEnd":593,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/native-assets.ts#L557-L593","documentation":"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.","triggerScenarios":"acquireCacheLock when handle.write of the lock record returns bytesWritten < record length — ENOSPC conditions, full tmpfs, or flaky network filesystems backing the cache.","commonSituations":"Docker containers with tiny tmpfs caches; disk-full CI runners; NFS-backed HOME directories.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await hydrateNativeBinary(); } catch (e) { if (/incomplete lock write/.test(String(e))) { /* free disk space, retry */ } throw e; }","preventionTips":["Monitor disk space where the cache lives","Use a local disk rather than tmpfs/NFS for caches","Retry hydration once after freeing space"],"tags":["native-assets","lock","disk-full","filesystem"],"backgroundTag":"disk-full","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}