{"record":{"id":"ff76e4221c8a9082","repo":"CherryHQ/cherry-studio","slug":"agent-storage-path-parent-is-not-a-directory-cu","errorCode":null,"errorMessage":"Agent storage path parent is not a directory: ${current}","messagePattern":"Agent storage path parent is not a directory: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/agents/agentDataDirectory.ts","lineNumber":67,"sourceCode":"    throw new Error(`Agent storage path escapes its root: ${target}`)\n  }\n\n  const rootStat = await lstatIfExists(root)\n  if (!rootStat?.isDirectory || rootStat.isSymbolicLink) {\n    throw new Error(`Agent storage root must be a real directory: ${root}`)\n  }\n\n  let current = root\n  const relative = path.relative(root, target)\n  for (const segment of relative ? relative.split(path.sep) : []) {\n    current = asAbsolutePath(path.join(current, segment))\n    const currentStat = await lstatIfExists(current)\n    if (!currentStat) break\n    if (currentStat.isSymbolicLink) {\n      throw new Error(`Agent storage path contains a symbolic link: ${current}`)\n    }\n    if (current !== target && !currentStat.isDirectory) {\n      throw new Error(`Agent storage path parent is not a directory: ${current}`)\n    }\n  }\n\n  const [realRoot, realTarget] = await Promise.all([\n    resolveRealOrNearestExistingPath(root),\n    resolveRealOrNearestExistingPath(target)\n  ])\n  if (realTarget !== realRoot && !isPathInside(realTarget, realRoot)) {\n    throw new Error(`Agent storage path resolves outside its root: ${target}`)\n  }\n}\n\n/** Ensure a Data/Agents path is a real directory contained by the Agent storage root. */\nexport async function ensureAgentStorageDirectory(agentsDataRoot: string, targetPath: string): Promise<void> {\n  await ensureDir(asAbsolutePath(path.resolve(agentsDataRoot)))\n  await assertAgentStoragePath(agentsDataRoot, targetPath)\n  await ensureDir(asAbsolutePath(path.resolve(targetPath)))\n  await assertAgentStoragePath(agentsDataRoot, targetPath)","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/agents/agentDataDirectory.ts#L49-L85","documentation":"Thrown by assertAgentStoragePath during the segment walk when an intermediate component (not the final target) exists but is not a directory — e.g. a file sits where a directory is expected on the path to the target. This blocks creating a directory path through a file (which would fail anyway) and catches corrupted/misstructured agent data trees.","triggerScenarios":"A file occupies a path segment that should be a directory: e.g. Data/Agents/<agentId> is a file (not a directory) while the target is Data/Agents/<agentId>/memory/file. The check is current !== target && !currentStat.isDirectory.","commonSituations":"Corrupted agent data where a directory was replaced by a file; a buggy write created a file at a directory path; partial migration leaving a file where a folder is expected; manual tampering with the data folder.","solutions":["Inspect the named path and remove or relocate the file blocking the directory path.","Re-create the expected directory structure via ensureAgentDataDirectory (after cleaning the obstruction).","Determine what wrote the file at a directory path to prevent recurrence.","Restore the agent data directory from a known-good backup if the structure is badly corrupted."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { lstatIfExists } from './agentDataDirectory'\n// Reject an intermediate segment that is a file\nfor (const seg of path.relative(root, target).split(path.sep)) {\n  current = path.join(current, seg)\n  const st = await lstatIfExists(current)\n  if (current !== target && st && !st.isDirectory) {\n    throw new Error(`Refusing: '${current}' is not a directory`)\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the agent data directory structure intact — do not let files occupy directory paths.","Recreate corrupted structure with ensureAgentDataDirectory after removing the obstruction.","Find the writer that created a file at a directory path to prevent recurrence."],"tags":["security","filesystem","agent","validation"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}