paperclipai/paperclip · error · Error
ACPX runtime directory must not be a filesystem root
Error message
ACPX runtime directory must not be a filesystem root
What it means
resolveAcpxRuntimeRoot additionally refuses to use the filesystem root ('/' on POSIX, drive root on Windows) as the runtime base. Because per-session paths are built by appending 'acpx/<session-dir>' under the root, using the root would scatter runtime state across the top of the filesystem. The error is thrown when realpath(runtimeDirectory) equals dirname(realpath(runtimeDirectory)).
Source
Thrown at packages/paperclip-runner/src/drivers/acpx/recovery-identity.ts:309
const metadata = await stat(workspacePath);
if (!metadata.isDirectory() || workspacePath === dirname(workspacePath)) {
throw new Error("ACPX working directory must be a non-root directory");
}
return workspacePath;
}
export async function resolveAcpxRuntimeRoot(
runtimeDirectory: string,
sessionId: string,
): Promise<string> {
if (!runtimeDirectory.trim())
throw new Error("ACPX runtime directory is required");
const root = await realpath(runtimeDirectory);
const metadata = await stat(root);
if (!metadata.isDirectory())
throw new Error("ACPX runtime directory must be a directory");
if (root === dirname(root))
throw new Error("ACPX runtime directory must not be a filesystem root");
return join(
resolve(root),
"acpx",
acpxRuntimeSessionDirectoryName(sessionId),
);
}
/**
* Return the stable, filesystem-safe directory name used for one normalized
* ACPX session below the runtime's `acpx` namespace.
*/
export function acpxRuntimeSessionDirectoryName(sessionId: string): string {
const readable = sessionId
.replace(/[^a-zA-Z0-9._-]/g, "_")
.replace(/^\.+$/, "session")
.slice(0, 80);
const suffix = createHash("sha256")
.update(sessionId)View on GitHub (pinned to 01ad858492)
Solutions
- Set runtimeDirectory to a dedicated, non-root directory (e.g. <data>/runtime).
- Check your env/config source: an empty or missing variable is probably falling back to "/" — fix the default.
- In containers, verify the data volume mounted correctly; a missing mount leaves the path resolving to root.
- Add a config-time check that the chosen directory is non-root before constructing the driver.
Example fix
// before
const dir = process.env.ACPX_RUNTIME_DIR ?? "/"; // root fallback
// after
const dir = process.env.ACPX_RUNTIME_DIR;
if (!dir || dir === "/") throw new Error("ACPX_RUNTIME_DIR must be a non-root directory"); Defensive patterns
Strategy: validation
Validate before calling
import { isAbsolute, resolve } from "node:path";
const root = resolve(runtimeDirectory);
if (root === "/" || /^[A-Z]:\\?$/i.test(root)) {
throw new Error("ACPX runtime directory must not be the filesystem root");
} Prevention
- Never default runtimeDirectory to "/"; require an explicit path.
- Verify container volumes actually mounted before starting the driver.
- Guard env-driven config with a non-root assertion at startup.
When it happens
Trigger: Calling runtimeRoot()/resolveAcpxRuntimeRoot with runtimeDirectory = "/" (or "C:\\", or a symlink resolving to the filesystem root).
Common situations: An unset/empty config variable defaulting to "/"; a shell variable like RUNTIME_DIR=${BASE:-/} expanding to the root; a container mount where the intended volume failed to mount, leaving only "/"; misconfigured Docker volume mapping.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ACPX runtime directory must be a directory
- Registered ${label} Paperclip config is missing its adjacent
- Registered base project workspace Paperclip config at ${conf
- ${label} does not exist at ${resolved}.
- ${label} is not a regular file at ${canonical}.
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/584f0c88a2ba35fe.
Report an issue: GitHub.