{"record":{"id":"5ff837c5b0f1b4bd","repo":"Yeachan-Heo/oh-my-codex","slug":"native-assets-unsafe-publication-lock","errorCode":null,"errorMessage":"[native-assets] unsafe publication lock","messagePattern":"\\[native-assets\\] unsafe publication lock","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/native-assets.ts","lineNumber":581,"sourceCode":"  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  }\n}\n\nasync function releaseCacheLock(lock: PublicationLock): Promise<ManagedNativeBinaryInspection | undefined> {","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/native-assets.ts#L563-L599","documentation":"The open lock file failed the safety stat: it is not a regular file or has a hard link count other than 1. Hard-linked or non-regular lock files are treated as unsafe because they enable lock-spoofing and aliasing in the multi-process cache protocol.","triggerScenarios":"acquireCacheLock when fstat on the newly created lock shows nlink !== 1 (someone hard-linked the lock) or the entry is not a regular file (e.g. named pipe or device).","commonSituations":"Multi-user caches with hard-link based dedup tools; caches manipulated by backup tools that hard-link; hostile shared /tmp-style directories.","solutions":["Delete the offending lock file named in the acquire path and retry.","Use a per-user cache root instead of a shared one.","Audit what is hard-linking or creating non-regular files inside the cache."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await hydrateNativeBinary(); } catch (e) { if (/unsafe publication lock/.test(String(e))) { /* remove the offending lock file, audit for hard-link tools, retry */ } throw e; }","preventionTips":["Use per-user cache roots","Don't run hard-link dedup/backup tools over the cache","Remove stale locks before retrying"],"tags":["native-assets","lock","hardlink","filesystem-security"],"backgroundTag":"file-corruption","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}