{"record":{"id":"07ceb8d5ccac7059","repo":"paperclipai/paperclip","slug":"a-sandbox-command-is-required","errorCode":null,"errorMessage":"A sandbox command is required.","messagePattern":"A sandbox command is required\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/createos/src/execute.ts","lineNumber":18,"sourceCode":"import { randomUUID } from \"node:crypto\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { PluginEnvironmentExecuteParams, PluginEnvironmentExecuteResult } from \"@paperclipai/plugin-sdk\";\nimport { CreateosApiError, CreateosClient, identifier, object } from \"./client.js\";\n\nconst MAX_LINE_BYTES = 1_048_576;\nconst MAX_CAPTURE_CHARS = 4_194_304;\n\nexport class CreateosCleanupError extends Error {}\n\nexport function shellQuote(value: string): string {\n  if (value.includes(\"\\0\")) throw new Error(\"Sandbox command values cannot contain NUL.\");\n  return `'${value.replace(/'/g, `'\"'\"'`)}'`;\n}\n\nfunction commandScript(params: PluginEnvironmentExecuteParams, stdinPath: string | null): string {\n  if (!params.command) throw new Error(\"A sandbox command is required.\");\n  const env = Object.entries(params.env ?? {}).map(([key, value]) => {\n    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key) || typeof value !== \"string\") {\n      throw new Error(\"Invalid sandbox environment variable.\");\n    }\n    return `${key}=${shellQuote(value)}`;\n  });\n  const command = [params.command, ...(params.args ?? [])].map(shellQuote).join(\" \");\n  return [\n    params.cwd ? `cd -- ${shellQuote(params.cwd)} || exit` : \"\",\n    `exec env ${env.join(\" \")} ${command}${stdinPath ? ` < ${shellQuote(stdinPath)}` : \"\"}`,\n  ].filter(Boolean).join(\"\\n\");\n}\n\nasync function* events(response: Response): AsyncGenerator<Record<string, unknown>> {\n  if (!response.body) throw new Error(\"CreateOS returned an empty process stream.\");\n  const reader = response.body.getReader();\n  const decoder = new TextDecoder();\n  let pending = \"\";","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/plugins/sandbox-providers/createos/src/execute.ts#L1-L36","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set params.command to the program to run, e.g. { command: 'bash', args: ['-c', 'ls -la'] }.","Ensure the command isn't an empty string — use a real executable name.","Check the calling code path for a conditional that drops the command field."],"exampleFix":"// before\nexec({ args: [\"-la\"] })\n// after\nexec({ command: \"ls\", args: [\"-la\"] })","handlingStrategy":"validation","validationCode":"if (typeof params.command !== 'string' || params.command.length === 0) throw new Error('params.command must be a non-empty string before execute()');","typeGuard":"function hasCommand(p) { return typeof p === 'object' && p !== null && typeof p.command === 'string' && p.command.length > 0; }","tryCatchPattern":null,"preventionTips":["Always pass command as the first, explicit field of execute params","Type execute params so command is required (non-optional)","Guard dynamic param construction with a required-fields check"],"tags":["validation","missing-argument","sandbox"],"backgroundTag":"missing-required-argument","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}