{"record":{"id":"a5fa11c6e4f0f99b","repo":"Yeachan-Heo/oh-my-codex","slug":"native-assets-unable-to-create-cache-root","errorCode":null,"errorMessage":"[native-assets] unable to create cache root","messagePattern":"\\[native-assets\\] unable to create cache root","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/native-assets.ts","lineNumber":620,"sourceCode":"    if (!sameFile(lock.identity, reopened) || reopened.text !== lock.record) return { state: 'cleanup-failed' };\n    const current = await lstat(lock.path);\n    if (!sameFile(lock.identity, { dev: current.dev, ino: current.ino, size: current.size }) || !current.isFile() || current.nlink !== 1) return { state: 'cleanup-failed' };\n    await unlink(lock.path);\n  } catch (error) { return absent(error) ? undefined : { state: 'cleanup-failed' }; }\n  return undefined;\n}\n\nasync function quarantineInvalid(path: string): Promise<void> {\n  try {\n    await lstat(path);\n    await rename(path, `${path}.quarantine.${uuid()}`);\n  } catch (error) { if (!absent(error)) throw error; }\n}\n\nasync function publishManagedNativeBinary(source: string, destination: string, platform: NodeJS.Platform, env: NodeJS.ProcessEnv): Promise<string | undefined> {\n  const configuredRoot = resolveNativeCacheRoot(env);\n  const root = await canonicalCacheRoot(configuredRoot, true);\n  if (!root) throw new Error('[native-assets] unable to create cache root');\n  destination = canonicalDescendantPath(destination, configuredRoot, root);\n  await validateDescendant(destination, root, true);\n  const lock = await acquireCacheLock(destination, env);\n  const attempt = uuid();\n  const tempBinary = join(dirname(destination), `.${attempt}.tmp.bin`);\n  const tempSidecar = join(dirname(destination), `.${attempt}.tmp.sha256`);\n  const revalidatePublicationPaths = async (): Promise<void> => {\n    await validateDescendant(destination, root, false);\n    await validateDescendant(sidecarPath(destination), root, false);\n    await validateDescendant(lock.path, root, false);\n    await validateDescendant(tempBinary, root, false);\n    await validateDescendant(tempSidecar, root, false);\n  };\n  let primaryError: unknown;\n  try {\n    await revalidatePublicationPaths();\n    const existing = await inspectManagedNativeBinary(destination, env);\n    if (existing.state === 'verified') return existing.path;","sourceCodeStart":602,"sourceCodeEnd":638,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/native-assets.ts#L602-L638","documentation":"The configured native cache root could not be created (or canonicalized) — canonicalCacheRoot returned undefined after attempting mkdir(recursive). Without a usable root, managed binary publication cannot proceed.","triggerScenarios":"publishManagedNativeBinary when the cache root path is unwritable (EACCES), sits on a read-only mount, or its parent cannot be traversed; canonicalCacheRoot swallows absent errors but fails to produce a canonical root.","commonSituations":"Running as a user without write access to the default cache location (e.g. root-owned ~/.cache after sudo misuse); read-only container filesystems; XDG-style env overrides pointing to invalid paths.","solutions":["Fix permissions/ownership of the cache root path (chown -R $(whoami)).","Set the cache-root env override to a writable location (e.g. a tmpfs or project-local dir).","In containers, ensure HOME and the cache dir are on a writable volume."],"exampleFix":"# before: cache root /root/.cache/omx owned by root, running as app\nsudo chown -R app:app /root/.cache/omx\n# or: export OMX_NATIVE_CACHE_ROOT=/tmp/omx-cache  # (use the library's documented override)","handlingStrategy":"validation","validationCode":"import { accessSync, constants } from 'node:fs';\nfunction cacheRootWritable(root: string): boolean { try { accessSync(root, constants.W_OK | constants.X_OK); return true; } catch { try { accessSync(require('node:path').dirname(root), constants.W_OK); return true; } catch { return false; } } }","typeGuard":null,"tryCatchPattern":"try { await hydrateNativeBinary(); } catch (e) { if (/unable to create cache root/.test(String(e))) { /* chown/chmod the cache dir or point env override at a writable path */ } throw e; }","preventionTips":["Ensure write access to the cache directory in containers","Set the cache-root env override to a writable volume","Avoid running hydration after sudo/root owned the cache dir"],"tags":["native-assets","cache","permissions","mkdir"],"backgroundTag":"permission-denied","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}