CherryHQ/cherry-studio · critical · Error
Agent storage root must be a real directory: ${root}
Error message
Agent storage root must be a real directory: ${root} What it means
Thrown by assertAgentStoragePath when the agents data root itself is missing, not a directory, or is a symbolic link. The check uses lstat (does not follow symlinks) and requires rootStat.isDirectory truthy and isSymbolicLink false. This ensures the managed root is a real directory before any segment walking begins, preventing a symlinked root from redirecting all operations.
Source
Thrown at src/main/ai/agents/agentDataDirectory.ts:54
}
}
}
}
/**
* Validate a path in Data/Agents without following symbolic links in the
* managed root or any path component below it.
*/
export async function assertAgentStoragePath(agentsDataRoot: string, targetPath: string): Promise<void> {
const root = asAbsolutePath(path.resolve(agentsDataRoot))
const target = asAbsolutePath(path.resolve(targetPath))
if (target !== root && !isPathInside(target, root)) {
throw new Error(`Agent storage path escapes its root: ${target}`)
}
const rootStat = await lstatIfExists(root)
if (!rootStat?.isDirectory || rootStat.isSymbolicLink) {
throw new Error(`Agent storage root must be a real directory: ${root}`)
}
let current = root
const relative = path.relative(root, target)
for (const segment of relative ? relative.split(path.sep) : []) {
current = asAbsolutePath(path.join(current, segment))
const currentStat = await lstatIfExists(current)
if (!currentStat) break
if (currentStat.isSymbolicLink) {
throw new Error(`Agent storage path contains a symbolic link: ${current}`)
}
if (current !== target && !currentStat.isDirectory) {
throw new Error(`Agent storage path parent is not a directory: ${current}`)
}
}
const [realRoot, realTarget] = await Promise.all([
resolveRealOrNearestExistingPath(root),View on GitHub (pinned to 726446b54c)
Solutions
- Create the root as a real directory first via ensureAgentStorageDirectory (which calls ensureDir then asserts).
- If the root is a symlink or file, remove/replace it with a real directory — do not weaken the check.
- Ensure no external process (sync, backup, migration tool) replaces the Data/Agents directory with a symlink.
- Verify the application path configuration resolves agentsDataRoot to the intended on-disk directory.
Example fix
// before (asserting before the root exists) await assertAgentStoragePath(agentsDataRoot, target) // root missing -> throws // after await ensureAgentStorageDirectory(agentsDataRoot, target) // creates + asserts
Defensive patterns
Strategy: validation
Validate before calling
import { lstatIfExists } from './agentDataDirectory' // or inline lstat
const stat = await lstatIfExists(path.resolve(agentsDataRoot))
if (!stat?.isDirectory || stat.isSymbolicLink) {
throw new Error(`Agents root '${agentsDataRoot}' must be a real directory`)
} Prevention
- Create the agents root via ensureAgentStorageDirectory before asserting against it.
- Never allow the Data/Agents root to be a symlink or a file.
- Audit that no sync/backup tool replaces the root directory with a link.
When it happens
Trigger: The Data/Agents root does not exist yet (not created); it exists but is a file rather than a directory; it is a symbolic link to another location. Calling assertAgentStoragePath before ensureAgentStorageDirectory has created the root would also surface this.
Common situations: First run before the directory is initialized; a user or another process replaced the directory with a symlink or a file; a corrupted/Partially-set-up data folder; calling the assert directly instead of via ensureAgentStorageDirectory.
Related errors
- Agent storage path escapes its root: ${target}
- Agent storage path contains a symbolic link: ${current}
- Agent storage path parent is not a directory: ${current}
- Agent storage path resolves outside its root: ${target}
- Agent storage directory must be a real directory: ${targetPa
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/a57e3f2986493262.
Report an issue: GitHub.