{"record":{"id":"297af1585be4458c","repo":"Yeachan-Heo/oh-my-codex","slug":"native-assets-lock-readback-mismatch","errorCode":null,"errorMessage":"[native-assets] lock readback mismatch","messagePattern":"\\[native-assets\\] lock readback mismatch","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/native-assets.ts","lineNumber":578,"sourceCode":"async 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\n      await new Promise<void>((done) => setTimeout(done, LOCK_RETRY_MS));\n    }\n  }","sourceCodeStart":560,"sourceCodeEnd":596,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/native-assets.ts#L560-L596","documentation":"After writing the lock record, reading it back yielded fewer bytes or different content than written. The readback equality check ensures the lock file on disk exactly matches what this process wrote; mismatch means concurrent interference or a broken filesystem.","triggerScenarios":"acquireCacheLock when the immediate read of the just-written lock file differs from the record — another process overwrote the lock, or the storage layer is inconsistent (NFS caching, container overlayfs races).","commonSituations":"Two hydration processes racing on the same cache key; network/overlay filesystems with weak coherence; antivirus or sync agents (Dropbox/OneDrive) rewriting files in the cache.","solutions":["Ensure only one hydration process runs per cache key; the timeout error message includes guidance on removing stale locks.","Move the cache off synced/network filesystems.","Retry hydration after the race clears."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await hydrateNativeBinary(); } catch (e) { if (/lock readback mismatch/.test(String(e))) { await sleep(1000); return hydrateNativeBinary(); } throw e; }","preventionTips":["Serialize hydration processes per cache key","Keep caches off synced filesystems (Dropbox/OneDrive)","Exclude cache dirs from antivirus scanning"],"tags":["native-assets","lock","race-condition","filesystem"],"backgroundTag":"file-corruption","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}