paperclipai/paperclip · error

A sandbox command is required.

Error message

A sandbox command is required.

What it means

commandScript builds the shell script sent to the CreateOS sandbox and requires a non-empty params.command. Without a command there is nothing to execute, so the plugin fails fast rather than sending an empty exec line to the remote host.

Solutions

  1. Set params.command to the program to run, e.g. { command: 'bash', args: ['-c', 'ls -la'] }.
  2. Ensure the command isn't an empty string — use a real executable name.
  3. Check the calling code path for a conditional that drops the command field.

Example fix

// before
exec({ args: ["-la"] })
// after
exec({ command: "ls", args: ["-la"] })
Defensive patterns

Strategy: validation

Validate before calling

if (typeof params.command !== 'string' || params.command.length === 0) throw new Error('params.command must be a non-empty string before execute()');

Type guard

function hasCommand(p) { return typeof p === 'object' && p !== null && typeof p.command === 'string' && p.command.length > 0; }

Prevention

When it happens

Trigger: Calling execute (or the script-building path) with PluginEnvironmentExecuteParams where command is undefined, null, or an empty string — even when args or stdin are supplied.

Common situations: Constructing execute params programmatically and forgetting to set command; spreading an options object where command was conditionally deleted; passing only args expecting the plugin to infer the program.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/07ceb8d5ccac7059. Report an issue: GitHub.

Appendix: source

Thrown at packages/plugins/sandbox-providers/createos/src/execute.ts:18

import { randomUUID } from "node:crypto";
import { StringDecoder } from "node:string_decoder";
import { setTimeout as delay } from "node:timers/promises";
import type { PluginEnvironmentExecuteParams, PluginEnvironmentExecuteResult } from "@paperclipai/plugin-sdk";
import { CreateosApiError, CreateosClient, identifier, object } from "./client.js";

const MAX_LINE_BYTES = 1_048_576;
const MAX_CAPTURE_CHARS = 4_194_304;

export class CreateosCleanupError extends Error {}

export function shellQuote(value: string): string {
  if (value.includes("\0")) throw new Error("Sandbox command values cannot contain NUL.");
  return `'${value.replace(/'/g, `'"'"'`)}'`;
}

function commandScript(params: PluginEnvironmentExecuteParams, stdinPath: string | null): string {
  if (!params.command) throw new Error("A sandbox command is required.");
  const env = Object.entries(params.env ?? {}).map(([key, value]) => {
    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key) || typeof value !== "string") {
      throw new Error("Invalid sandbox environment variable.");
    }
    return `${key}=${shellQuote(value)}`;
  });
  const command = [params.command, ...(params.args ?? [])].map(shellQuote).join(" ");
  return [
    params.cwd ? `cd -- ${shellQuote(params.cwd)} || exit` : "",
    `exec env ${env.join(" ")} ${command}${stdinPath ? ` < ${shellQuote(stdinPath)}` : ""}`,
  ].filter(Boolean).join("\n");
}

async function* events(response: Response): AsyncGenerator<Record<string, unknown>> {
  if (!response.body) throw new Error("CreateOS returned an empty process stream.");
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let pending = "";

View on GitHub (pinned to 3f1d897a7c)