paperclipai/paperclip · critical

Daytona sandbox ${sandbox.id} is in an unrecoverable error s

Error message

Daytona sandbox ${sandbox.id} is in an unrecoverable error state: ${sandbox.errorReason ?? "unknown error"}

What it means

Thrown by ensureSandboxStarted when a sandbox is in the 'error' state and its recoverable flag is false, meaning the Daytona sandbox suffered an unrecoverable failure and cannot be restarted. The errorReason (or 'unknown error') from the sandbox is included.

Source

Thrown at packages/plugins/sandbox-providers/daytona/src/plugin.ts:378

}

function isValidUrl(value: string): boolean {
  try {
    new URL(value);
    return true;
  } catch {
    return false;
  }
}

async function ensureSandboxStarted(sandbox: Sandbox, timeoutSeconds: number): Promise<void> {
  if (sandbox.state === "started") return;
  if (sandbox.state === "error") {
    if (sandbox.recoverable) {
      await sandbox.recover(timeoutSeconds);
      return;
    }
    throw new Error(`Daytona sandbox ${sandbox.id} is in an unrecoverable error state: ${sandbox.errorReason ?? "unknown error"}`);
  }
  await sandbox.start(timeoutSeconds);
}

async function resolveSandboxWorkingDirectory(sandbox: Sandbox): Promise<string> {
  const root = (await sandbox.getWorkDir())?.trim()
    || (await sandbox.getUserHomeDir())?.trim()
    || "/home/daytona";
  const remoteCwd = path.posix.join(root, "paperclip-workspace");
  await sandbox.fs.createFolder(remoteCwd, "755");
  return remoteCwd;
}

async function detectSandboxShellCommand(sandbox: Sandbox, timeoutSeconds: number): Promise<"bash" | "sh"> {
  try {
    const result = await sandbox.process.executeCommand(
      "if command -v bash >/dev/null 2>&1; then printf bash; else printf sh; fi",
      undefined,

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Read sandbox.errorReason in the message to diagnose the underlying failure.
  2. Release the current lease and acquire a new sandbox (the unrecoverable one cannot be saved).
  3. If the image/snapshot is at fault, fix the template and recapture before re-acquiring.
  4. Check Daytona account quotas/limits that may have put the sandbox in an error state.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await ensureSandboxStarted(sandbox, timeoutSeconds);
} catch (e) {
  if (e instanceof Error && e.message.includes('unrecoverable error state')) {
    // release lease; acquire a new sandbox; do not retry on the same handle
  }
  throw e;
}

Prevention

When it happens

Trigger: ensureSandboxStarted is called for a sandbox whose state is 'error' and sandbox.recoverable is false. This occurs before any exec/sync that needs a started sandbox.

Common situations: The Daytona sandbox hit a fatal infrastructure error (image corruption, node loss, quota exhaustion, snapshot invalid); a previous recover attempt failed and flipped recoverable to false; long-idle sandbox that degraded past recovery; misconfigured image/snapshot that cannot boot.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/768a5059e6660907. Report an issue: GitHub.