paperclipai/paperclip · warning

Failed to stop Daytona sandbox during lease release: ${forma

Error message

Failed to stop Daytona sandbox during lease release: ${formatErrorMessage(error)}. Attempting delete instead.

What it means

During Daytona sandbox lease release with reuseLease=true, the plugin calls sandbox.stop() to preserve the sandbox for reuse. If stop() throws (API error, timeout, sandbox already gone server-side), it logs this warning and falls back to sandbox.delete() so the sandbox does not leak; if delete also fails, a follow-up warning fires and the sandbox may be orphaned.

Source

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

      if (!sandbox) return;

      evictSandboxHandle(scope);
      await sandboxHandleActivityGates.waitForIdle(scope);
      await teardownSession(sandbox, scope);
      // Close every duplex channel on this lease before the stop or the delete,
      // so no channel outlives the sandbox and no stored channel id survives.
      await closeDaytonaDuplexChannelsForLease(params.providerLeaseId);

      if (config.reuseLease) {
        if (sandbox.state !== "stopped") {
          try {
            await sandbox.stop(toTimeoutSeconds(config.timeoutMs));
          } catch (error) {
            console.warn(
              `Failed to stop Daytona sandbox during lease release: ${formatErrorMessage(error)}. Attempting delete instead.`,
            );
            await sandbox.delete(toTimeoutSeconds(config.timeoutMs)).catch((deleteError) => {
              console.warn(
                `Failed to delete Daytona sandbox after stop failure: ${formatErrorMessage(deleteError)}`,
              );
            });
          }
        }
        return;
      }

      if (config.archiveOnRelease) {
        try {
          if (sandbox.state !== "stopped") {
            await sandbox.stop(toTimeoutSeconds(config.timeoutMs));
          }
          await sandbox.setAutoDeleteInterval(ARCHIVE_ON_RELEASE_AUTO_DELETE_MINUTES);
          await sandbox.archive();
          return;
        } catch (error) {
          console.warn(

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Check the sandbox's real state in the Daytona dashboard; if the follow-up delete warning also fired, delete the orphan manually.
  2. Increase the plugin's timeoutMs so stop/delete have room to complete.
  3. Check Daytona service status and API credentials if failures repeat.
  4. If sandbox reuse is not required, set reuseLease=false so release deletes directly and stop is never the dependent step.

Example fix

// before (daytona sandbox provider config)
{ "reuseLease": true, "timeoutMs": 5000 }

// after
{ "reuseLease": true, "timeoutMs": 30000 }
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await lease.release();
} catch (err) {
  // Stop-failure already fell back to delete inside the plugin; verify the sandbox
  // is actually gone before treating the release as clean.
  const stillExists = await daytonaClient.sandboxExists(lease.sandboxId);
  if (stillExists) {
    await janitor.queueManualDelete(lease.sandboxId); // reconcile later
  }
}

Prevention

When it happens

Trigger: reuseLease=true, sandbox state is not 'stopped', and sandbox.stop(toTimeoutSeconds(config.timeoutMs)) rejects — Daytona API 5xx/timeout, sandbox expired or already deleted remotely, or network interruption between paperclip and Daytona.

Common situations: Daytona cloud incident or rate limiting; timeoutMs too small for the sandbox to shut down; sandbox expired server-side while the lease still references it; stale local state after Daytona workspace events.

Related errors


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