paperclipai/paperclip · warning
Failed to stop Daytona sandbox during lease release
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.
Solutions
- Check the sandbox's real state in the Daytona dashboard; if the follow-up delete warning also fired, delete the orphan manually.
- Increase the plugin's timeoutMs so stop/delete have room to complete.
- Check Daytona service status and API credentials if failures repeat.
- 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
- Watch for the follow-up 'Failed to delete Daytona sandbox after stop failure' warn — that pair means a true orphan.
- Run a periodic reconciliation job comparing Daytona sandboxes against active leases.
- Size timeoutMs above the p99 sandbox stop/delete latency.
- Prefer reuseLease=false unless reuse is a measured requirement — it removes stop() from the release path.
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
- CreateOS command cleanup failed; process termination is…
- CreateOS command probe failed.
- CreateOS sandbox did not reach
- CreateOS transfer command failed.
- Daytona duplex channel: no cached sandbox resolves the…
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-08-18).
Data as JSON: /api/errors/825e18f0f8b59185.
Report an issue: GitHub.
Appendix: source
Thrown at packages/plugins/sandbox-providers/daytona/src/plugin.ts:2277
evictSandboxHandle(scope);
return {
providerLeaseId: null,
metadata: { expired: true, workspaceSentinel },
};
}
const shellCommand = await detectSandboxShellCommand(
sandbox,
toTimeoutSeconds(config.timeoutMs),
);
sandboxHandleCache.markFresh(scope);
sandboxHandleLeaseAdmissionStates.open(scope);
return {
providerLeaseId: sandbox.id,
metadata: leaseMetadata({
config,
sandbox,
shellCommand,
remoteCwd,
resumedLease: true,
resumedFromState,
sandboxState: "started",
workspaceSentinel,
}),
};
} catch (error) {
evictSandboxHandle(scope);
// A timeout, rate limit, or provider 5xx does not prove this sandbox is
// lost. Preserve the exact resource and let the host retry its recorded
// lease; replacement is permitted only after an explicit not-found or
// an immutable workspace identity mismatch.
throw error;
}
},
{ allowClosed: true },
);
},View on GitHub (pinned to 3f1d897a7c)