vercel/ai · error · Error
Cline private session directory ${JSON.stringify(privateSess
Error message
Cline private session directory ${JSON.stringify(privateSessionDir)} must be outside sessionWorkDir ${JSON.stringify(input.sessionWorkDir)}. What it means
When resolving a Cline private session directory, the harness verifies the resolved directory lies strictly outside the session working directory using path.posix.relative. If the resulting relative path is empty (same directory) or does not escape via '../' and is not absolute, the configuration is considered unsafe and this error is thrown. The harness requires private session state to be isolated from the shared session work directory.
Source
Thrown at packages/harness-cline/src/cline-resume-state.ts:61
readonly sessionWorkDir: string;
readonly sessionId: string;
}): string {
const sessionKey = createHash('sha256').update(input.sessionId).digest('hex');
const privateSessionDir = path.posix.join(
input.sandboxHomeDir,
'.ai-sdk',
'harness-cline',
sessionKey,
);
const relativePath = path.posix.relative(
input.sessionWorkDir,
privateSessionDir,
);
if (
relativePath === '' ||
(!relativePath.startsWith('../') && !path.posix.isAbsolute(relativePath))
) {
throw new Error(
`Cline private session directory ${JSON.stringify(privateSessionDir)} must be outside sessionWorkDir ${JSON.stringify(input.sessionWorkDir)}.`,
);
}
return privateSessionDir;
}
function resolveContainedSandboxPath(input: {
readonly privateSessionDir: string;
readonly historyFileName: string;
}): string {
const historyDir = path.posix.resolve(input.privateSessionDir);
const filePath = path.posix.resolve(
historyDir,
safeClineHistoryFileName(input.historyFileName),
);
const relativePath = path.posix.relative(historyDir, filePath);
if (
relativePath === '' ||View on GitHub (pinned to 69428b1f8b)
Solutions
- Set privateSessionDir to a directory on a different branch of the filesystem than sessionWorkDir (e.g. a sibling directory or a path under a dedicated state root).
- Verify with path.posix.relative(sessionWorkDir, privateSessionDir) that the result starts with '../' or is absolute before calling the API.
- If you intended the private dir to be a subfolder, instead create a sibling folder outside sessionWorkDir and point privateSessionDir at it.
Example fix
// before
createClineSession({ sessionWorkDir: '/work/session-1', privateSessionDir: '/work/session-1/private' });
// after
createClineSession({ sessionWorkDir: '/work/session-1', privateSessionDir: '/work/.cline-private/session-1' }); Defensive patterns
Strategy: validation
Validate before calling
import path from 'node:path';
function isPrivateDirOutsideWorkDir(sessionWorkDir: string, privateSessionDir: string): boolean {
const rel = path.posix.relative(path.posix.resolve(sessionWorkDir), path.posix.resolve(privateSessionDir));
return rel !== '' && (rel.startsWith('../') || path.posix.isAbsolute(rel));
}
if (!isPrivateDirOutsideWorkDir(input.sessionWorkDir, input.privateSessionDir)) {
throw new Error('privateSessionDir must be outside sessionWorkDir');
} Try / catch
try {
const session = await createClineSession(input);
} catch (e) {
if (e instanceof Error && e.message.includes('must be outside sessionWorkDir')) {
// fix config: choose a sibling/external directory
} else throw e;
} Prevention
- Keep private Cline state under a dedicated root (e.g. ~/.cline-private or a sibling of the work dir), never inside it.
- Add a unit test asserting path.posix.relative(workDir, privateDir).startsWith('../') for your default config.
- If sessionWorkDir is dynamic, compute privateSessionDir from a fixed root, not from the work dir.
When it happens
Trigger: Calling createClineSession (via resolveClinePrivateSessionDirectory) with privateSessionDir set equal to sessionWorkDir, or set to a relative path that resolves to a subdirectory inside sessionWorkDir (e.g. './private' inside the work dir), so path.posix.relative returns '' or a non-'../' path.
Common situations: Configuring privateSessionDir as a subfolder of the session work directory for convenience; passing the same base path to both options; copy-pasting config where sessionWorkDir was changed to a broader parent directory that now contains the private dir; using a relative path whose resolution lands inside the work dir.
Related errors
- Invalid argument for parameter model: model ${model.provider
- Pi private session directory ${JSON.stringify(privateSession
- Unsupported output: ${_exhaustiveCheck}
- Invalid argument for parameter output: Invalid output type.
- Model could not be resolved
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/8d27a7538fb46333.
Report an issue: GitHub.