CherryHQ/cherry-studio · error · Error
Session workspace is unavailable: ${workspaceRoot}
Error message
Session workspace is unavailable: ${workspaceRoot} What it means
Thrown by resolveWorkspaceFile() when realpath(workspaceRoot) fails with ENOENT or ENOTDIR. Unlike the per-file 'File not found' error, this specifically indicates the workspace root directory itself is gone. The comment in the source explains: a bare ENOENT naming the root would read like 'your file_path is wrong', so this is wrapped to tell the agent the session workspace itself is unavailable, preventing wasted retries on alternative file paths.
Source
Thrown at src/main/ai/channels/security/WorkspaceFileGuard.ts:33
* inside it. `realpath` defeats `../` and symlink escape; reading happens on a single
* fd over the canonical path so the stat/size check and the read see the same inode.
*
* This is defense-in-depth against traversal mistakes and prompt injection picking a
* wrong path — not a sandbox against an agent with code execution (which can already
* read arbitrary files and exfiltrate them as message text). See #16566.
*/
export async function resolveWorkspaceFile(workspaceRoot: string, userPath: string): Promise<FileAttachment> {
const requested = path.resolve(workspaceRoot, userPath)
let realRoot: string
try {
realRoot = await realpath(workspaceRoot)
} catch (error) {
// The root is a caller invariant, but if the session workspace is gone a bare ENOENT
// naming the root reads like "your file_path is wrong" — wrap it so the agent doesn't
// waste retries on other paths.
if (isErrnoException(error) && (error.code === 'ENOENT' || error.code === 'ENOTDIR')) {
throw new Error(`Session workspace is unavailable: ${workspaceRoot}`)
}
throw error
}
let realTarget: string
try {
realTarget = await realpath(requested)
} catch (error) {
if (isErrnoException(error) && (error.code === 'ENOENT' || error.code === 'ENOTDIR')) {
throw new Error(`File not found in workspace: ${userPath}`)
}
throw error
}
if (realTarget !== realRoot && !realTarget.startsWith(realRoot + path.sep)) {
throw new Error(`Path is outside the workspace: ${userPath}`)
}
View on GitHub (pinned to 726446b54c)
Solutions
- Verify the session workspace directory still exists at the path given by workspaceRoot — if it was cleaned, recreate it or start a new session.
- If this is a crash-restart path, ensure the session lifecycle recreates the workspace directory before rehydrating agent state.
- If running on a temp directory, increase the OS temp-cleanup interval or move workspaces to a stable application-managed path via application.getPath().
Defensive patterns
Strategy: try-catch
Validate before calling
import { exists } from '@main/utils/file'
// Check workspace exists before resolving files
const workspaceExists = await exists(workspaceRoot)
if (!workspaceExists) {
throw new Error(`Workspace not found, recreating or starting new session: ${workspaceRoot}`)
} Try / catch
try {
return await resolveWorkspaceFile(workspaceRoot, userPath)
} catch (error) {
if (error instanceof Error && error.message.startsWith('Session workspace is unavailable:')) {
// The workspace itself is gone — no retry on alternative paths will help
logger.error('Session workspace missing', { workspaceRoot })
throw new Error('Session workspace was deleted. Start a new session.')
}
throw error
} Prevention
- Use application.getPath() for workspace roots to ensure they live in a stable, app-managed directory.
- Implement workspace lifecycle hooks that verify directory existence on session resume.
- Avoid OS temp directories for long-lived sessions — temp reapers can clean them unexpectedly.
When it happens
Trigger: Called from agent document tools (cherryDocumentTools.ts:84, cherryAutonomyTools.ts:436) when an agent attempts to read a workspace file but the workspace directory was deleted, unmounted, or the session's workspacePath was never created. This is a caller-invariant violation: the workspace root is expected to exist for the entire session lifetime.
Common situations: The session workspace temp directory was cleaned by an OS temp-reaper or manual cleanup while the agent was still running; a crash-restart scenario where the workspace path was persisted but the directory was not recreated; the workspace was on a removable drive that was ejected; a workspace creation race where the agent started before the directory was fully set up.
Related errors
- File not found in workspace: ${userPath}
- Path is outside the workspace: ${userPath}
- File not found: ${displayPath}
- File not found: ${userPath}
- Not a regular file: ${displayPath}
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/b007c54d8d0054b9.
Report an issue: GitHub.