paperclipai/paperclip · error

Failed to create remote workspace directory

Error message

Failed to create remote workspace directory '${remoteCwd}': mkdir exited with code ${exitCode}

What it means

Thrown by ensureRemoteWorkspace in the Modal sandbox provider. Fires when the one-shot exec that mkdirs the remote workspace directory exits non-zero, so the plugin cannot set up the workspace cwd before running commands.

Solutions

  1. Check permissions and path validity on the remote sandbox; create parent dirs or fix remoteCwd.
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at packages/plugins/sandbox-providers/modal/src/plugin.ts:264 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18). Data as JSON: /api/errors/40512f54807b0ab1. Report an issue: GitHub.

Appendix: source

Thrown at packages/plugins/sandbox-providers/modal/src/plugin.ts:264

    'if [ -f "$HOME/.profile" ]; then . "$HOME/.profile" >/dev/null 2>&1 || true; fi',
    'if [ -f "$HOME/.bash_profile" ]; then . "$HOME/.bash_profile" >/dev/null 2>&1 || true; elif [ -f "$HOME/.bashrc" ]; then . "$HOME/.bashrc" >/dev/null 2>&1 || true; fi',
    'if [ -f "$HOME/.zprofile" ]; then . "$HOME/.zprofile" >/dev/null 2>&1 || true; fi',
  ];
  if (input.cwd) {
    lines.push(`cd ${shellQuote(input.cwd)}`);
  }
  lines.push(finalLine);
  return lines.join(" && ");
}

async function ensureRemoteWorkspace(sandbox: Sandbox, remoteCwd: string): Promise<void> {
  // Use a one-shot exec to mkdir -p; Modal does not expose a direct
  // filesystem mkdir helper and creating a file via `open()` does not create
  // intermediate directories.
  const proc = await sandbox.exec(["sh", "-lc", `mkdir -p ${shellQuote(remoteCwd)}`]);
  const exitCode = await proc.wait();
  if (exitCode !== 0) {
    throw new Error(
      `Failed to create remote workspace directory '${remoteCwd}': mkdir exited with code ${exitCode}`,
    );
  }
}

async function stageStdin(sandbox: Sandbox, stdin: string, remotePath: string): Promise<void> {
  const file = await sandbox.open(remotePath, "w");
  try {
    await file.write(new TextEncoder().encode(stdin));
    await file.flush();
  } finally {
    await file.close().catch(() => undefined);
  }
}

async function deleteStdinPath(sandbox: Sandbox, remotePath: string): Promise<void> {
  // Best-effort cleanup of the staged stdin file. We swallow errors because
  // it is fine for the file to outlive the sandbox if it is going to be

View on GitHub (pinned to a7e689b3c3)