paperclipai/paperclip · error · Error
Could not create working directory "${cwd}": ${reason}
Error message
Could not create working directory "${cwd}": ${reason} What it means
Thrown by ensureAbsoluteDirectory when createIfMissing was true, the path did not exist (ENOENT), and the subsequent fs.mkdir(cwd, {recursive:true}) or the post-mkdir assertDirectory itself threw. The wrapped reason is the underlying error message — typically EACCES (permission denied), EROFS (read-only filesystem), ENOSPC, or a parent path component that is a file.
Source
Thrown at packages/adapter-utils/src/server-utils.ts:2452
try {
await assertDirectory();
return;
} catch (err) {
const code = (err as NodeJS.ErrnoException).code;
if (!opts.createIfMissing || code !== "ENOENT") {
if (code === "ENOENT") {
throw new Error(`Working directory does not exist: "${cwd}"`);
}
throw err instanceof Error ? err : new Error(String(err));
}
}
try {
await fs.mkdir(cwd, { recursive: true });
await assertDirectory();
} catch (err) {
const reason = err instanceof Error ? err.message : String(err);
throw new Error(`Could not create working directory "${cwd}": ${reason}`);
}
}
export async function resolvePaperclipSkillsDir(
moduleDir: string,
additionalCandidates: string[] = [],
): Promise<string | null> {
const candidates = [
...PAPERCLIP_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path.resolve(moduleDir, relativePath)),
...additionalCandidates.map((candidate) => path.resolve(candidate)),
];
const seenRoots = new Set<string>();
for (const root of candidates) {
if (seenRoots.has(root)) continue;
seenRoots.add(root);
const isDirectory = await fs.stat(root).then((stats) => stats.isDirectory()).catch(() => false);
if (isDirectory) return root;View on GitHub (pinned to 67001ec6eb)
Solutions
- Grant write permission on the parent directory to the running user (chown/chmod), or choose a writable location.
- If on a read-only filesystem, mount a writable volume at or above the path.
- Free disk space if ENOSPC, and check `reason` in the error for the exact errno.
- Ensure no parent path component is a file (mkdir -p fails with ENOTDIR in that case) and fix the upstream layout.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check writability of the parent before relying on mkdir.
import { access } from 'node:fs/promises';
try { await access(path.dirname(cwd), fsConstants.W_OK); } catch { throw new Error(`parent of ${cwd} is not writable`); } Try / catch
try { await ensureAbsoluteDirectory(cwd, { createIfMissing: true }); } catch (err) { logger.error('cannot create working dir', { cwd, reason: (err as Error).message }); throw err; } Prevention
- Ensure the running user owns or can write the parent directory.
- Mount a writable volume at read-only paths.
- Free disk space and check errno in the wrapped reason.
When it happens
Trigger: ensureAbsoluteDirectory(cwd, {createIfMissing:true}) where mkdir fails: the orchestrator user lacks write permission on the parent, the filesystem is read-only, the disk is full, or a parent segment is a regular file (ENOTDIR).
Common situations: Running as a user without write access to the target parent (e.g. /var/lib/...); container with a read-only rootfs or a read-only mount at the path; disk full; a parent like '/data' is a file not a directory; SELinux/AppArmor denial.
Related errors
- Working directory must be an absolute path: "${cwd}"
- Working directory is not a directory: "${cwd}"
- Working directory does not exist: "${cwd}"
- Could not locate local Paperclip skills directory. Expected
- Export output path ${root} exists and is not a directory.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/0785922f66f9b599.
Report an issue: GitHub.