{"record":{"id":"80bc2589562fb462","repo":"EveryInc/compound-engineering-plugin","slug":"could-not-validate-collectionpath-after-taking","errorCode":null,"errorMessage":"Could not validate ${collectionPath} after taking it. The entry is preserved at ${recoveryPath} (${reason})","messagePattern":"Could not validate (.+?) after taking it\\. The entry is preserved at (.+?) \\((.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/dev/codex-dev.ts","lineNumber":316,"sourceCode":"  const parentPath = path.dirname(collectionPath)\n  const recoveryDir = await fs.mkdtemp(\n    path.join(parentPath, `.${path.basename(collectionPath)}.recovery-`),\n  )\n  const recoveryPath = path.join(recoveryDir, \"entry\")\n\n  try {\n    await fs.rename(collectionPath, recoveryPath)\n  } catch (error) {\n    await fs.rmdir(recoveryDir).catch(() => undefined)\n    if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return changed()\n    throw error\n  }\n\n  try {\n    await options.onTakenForTest?.(recoveryPath)\n  } catch (error) {\n    const reason = error instanceof Error ? error.message : String(error)\n    throw new Error(\n      `Could not validate ${collectionPath} after taking it. ` +\n        `The entry is preserved at ${recoveryPath} (${reason})`,\n    )\n  }\n\n  const stat = await fs.lstat(recoveryPath)\n  let actualTarget: string | undefined\n  if (stat.isSymbolicLink()) {\n    actualTarget = await fs.readlink(recoveryPath)\n  }\n\n  if (stat.isSymbolicLink() && actualTarget === expectedTarget) {\n    await fs.unlink(recoveryPath)\n    await fs.rmdir(recoveryDir)\n    return true\n  }\n\n  const restorationFailed = (error: unknown): never => {","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/EveryInc/compound-engineering-plugin/blob/c9c10f8c75412c7232cb2bd663e5fd1cea98d84e/src/dev/codex-dev.ts#L298-L334","documentation":"removeManagedCollectionLink() moves the entry to a temp recovery directory and hands it to options.onTakenForTest for post-removal validation. If that callback throws, the original entry is kept at recoveryPath and the code re-raises with its location so nothing is lost. This is a safety net ensuring the 'taken' entry is never silently dropped when validation cannot complete.","triggerScenarios":"The onTakenForTest callback supplied by replaceManagedCollectionLink / restoreLocalCollection / removeLocalCollection throws — any filesystem error while validating or restoring the taken entry (permission denied, ENOENT on the recovery path, disk full).","commonSituations":"Temp directory on a read-only or full volume so the recovery copy cannot be read back; sandbox/permissions blocking access to the mkdtemp recovery directory; a bug in the caller's validation callback throwing spuriously.","solutions":["Read the recoveryPath from the error message — the original entry is intact there","Check free space and write permissions on the OS temp directory used for recoveryPath","Manually move the entry back: `mv <recoveryPath> <collectionPath>` to restore the previous state","Re-run the removal after fixing the underlying validation failure"],"exampleFix":"// before — recovery dir unwritable, callback fails\n// Error: Could not validate ... (EACCES: permission denied, scandir '/tmp/...')\n\n// after\n$ TMPDIR=/tmp  # or fix perms on the configured temp dir\n$ mv \"$recoveryPath\" \"$collectionPath\" && retry the codex:dev command","handlingStrategy":"try-catch","validationCode":"import { fs } from \"...\";\nawait fs.access(path.dirname(recoveryPath)); // recovery dir is readable\nconst stat = await fs.stat(recoveryPath);     // taken entry actually exists","typeGuard":null,"tryCatchPattern":"try {\n  await removeLocalCollection(context);\n} catch (e) {\n  const m = String(e).match(/preserved at (\\S+)/);\n  if (m) console.error(`original entry kept at ${m[1]}; restore manually if needed`);\n  else throw e;\n}","preventionTips":["Ensure the OS temp directory is writable and has free space","Avoid running under sandboxes that deny access to $TMPDIR","Keep onTakenForTest callbacks simple and side-effect free"],"tags":["filesystem","validation","recovery","codex-dev"],"backgroundTag":"validation-callback-failed","analyzedSha":"c9c10f8c75412c7232cb2bd663e5fd1cea98d84e","analyzedAt":"2026-08-31T15:18:07.959Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}