paperclipai/paperclip · error
Unable to create a Linux-safe Paperclip sandbox proxy socket
Error message
Unable to create a Linux-safe Paperclip sandbox proxy socket directory.
What it means
Thrown by createNetworkProxyTempDir after both candidate base directories (/tmp and os.tmpdir()) fail to yield a directory whose proxy.sock path fits within 107 bytes, or when mkdtemp itself fails on both. The original failure is attached via { cause: lastError } so callers can inspect why both candidates failed.
Source
Thrown at packages/adapter-utils/src/local-process-sandbox.ts:194
async function createNetworkProxyTempDir(): Promise<string> {
const candidates = Array.from(new Set(["/tmp", os.tmpdir()]));
let lastError: unknown;
for (const baseDir of candidates) {
try {
const tempDir = await fs.mkdtemp(path.join(baseDir, NETWORK_PROXY_TEMP_PREFIX));
try {
assertUnixSocketPathLength(path.join(tempDir, "proxy.sock"));
return tempDir;
} catch (error) {
await fs.rm(tempDir, { recursive: true, force: true });
lastError = error;
}
} catch (error) {
lastError = error;
}
}
throw new Error("Unable to create a Linux-safe Paperclip sandbox proxy socket directory.", { cause: lastError });
}
function parseTrustedNetworkUrl(value: string): NetworkAllowlistRule | null {
try {
const parsed = new URL(value);
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
return {
hostname: parsed.hostname.toLowerCase(),
port: parsed.port || (parsed.protocol === "https:" ? "443" : "80"),
};
} catch {
return null;
}
}
function writeProxyError(response: http.ServerResponse, status: number, code: string, message: string): void {
const body = `${JSON.stringify({ error: { code, message } })}\n`;
response.writeHead(status, {View on GitHub (pinned to 67001ec6eb)
Solutions
- Inspect err.cause — it tells you whether both candidates hit a length limit, a permission error, or disk-full.
- Set TMPDIR to a short writable path that is NOT the same as the failing /tmp candidate: export TMPDIR=/var/tmp or a dedicated /run/paperclip owned by the runner user.
- Ensure the runner user has write + create permissions on /tmp (mode 1777) and on the configured TMPDIR.
- Free inodes/disk on the tmpfs backing /tmp (df -h /tmp; df -i /tmp) — mkdtemp fails with ENOSPC when either is exhausted.
Example fix
// before: both /tmp and TMPDIR unusable
// err.cause === EACCES on /tmp, EACCES on /var/run/user/1000/long/...
// after: dedicated short, writable dir
await fs.mkdir("/run/paperclip", { recursive: true, mode: 0o700 });
process.env.TMPDIR = "/run/paperclip";
const target = await buildLocalProcessSandboxSpawnTarget(input); Defensive patterns
Strategy: try-catch
Validate before calling
async function preflightTempDirs(): Promise<void> {
const candidates = Array.from(new Set(["/tmp", process.env.TMPDIR ?? "/tmp"]));
for (const base of candidates) {
try {
const probe = await fs.mkdtemp(path.join(base, "paperclip-preflight-"));
const sock = path.join(probe, "proxy.sock");
if (Buffer.byteLength(sock) > 107) throw new Error(`socket path too long under ${base}`);
await fs.rm(probe, { recursive: true, force: true });
return; // at least one candidate works
} catch (error) {
// try next
}
}
throw new Error("No usable temp dir for sandbox; set TMPDIR to a short, writable path.");
} Try / catch
try {
return await buildLocalProcessSandboxSpawnTarget(input);
} catch (error) {
if (error instanceof Error && error.message.startsWith("Unable to create a Linux-safe")) {
const cause = (error as Error & { cause?: unknown }).cause;
throw new ConfigError(`Sandbox temp dir unavailable. Cause: ${String(cause)}`, { cause: error });
}
throw error;
} Prevention
- Ensure both /tmp and TMPDIR are writable by the runner user (mode 1777 or owned).
- Pin TMPDIR to a short, dedicated path like /run/paperclip.
- Monitor free inodes and disk on tmpfs (df -h -i /tmp); mkdtemp fails on exhaustion.
When it happens
Trigger: Both /tmp and TMPDIR are unwritable, both are mounted on paths long enough that the generated paperclip-network-sandbox-XXXXXXXX/proxy.sock path exceeds 107 bytes, or both mkdtemp calls throw (ENOSPC, EROFS, EACCES). The function tries /tmp first then os.tmpdir(); only when both fail (or both produce oversized paths) does this throw.
Common situations: Hardened containers where /tmp is read-only or tmpfs-size-limited, CI runners where TMPDIR is set to a long path AND /tmp is overridden to the same long path, or sandbox environments where the process has no write access to either candidate. The cause field typically holds EACCES, ENOSPC, or a sibling assertUnixSocketPathLength error.
Related errors
- Paperclip sandbox proxy socket path is ${pathBytes} bytes, e
- Local process filesystem and network scopes are currently su
- filesystemScope must be "workspace".
- Sandbox cwd "${cwd}" must be inside workspaceDir "${workspac
- Writable sandbox path "${normalizedExtraPath}" is outside sy
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/48eed07abc12515a.
Report an issue: GitHub.