paperclipai/paperclip · error
Daytona sandbox lease ${scope.providerLeaseId} is no longer
Error message
Daytona sandbox lease ${scope.providerLeaseId} is no longer active. What it means
Thrown by withSandboxActivityGate at loop entry when the lease admission state is closed (and allowClosed is not set). This is the first of three identical-throw sites in the gate loop; it blocks any new activity on a lease that is no longer active before checking teardown/activity gates.
Source
Thrown at packages/plugins/sandbox-providers/daytona/src/plugin.ts:1038
function isClosed(scope: SandboxScope): boolean {
return states.get(key(scope)) === true;
}
function reset(): void {
states.clear();
}
return { open, close, isClosed, reset };
})();
async function withSandboxActivityGate<T>(
scope: SandboxScope,
fn: () => Promise<T>,
options: SandboxLeaseAdmissionOptions = {},
): Promise<T> {
while (true) {
if (!options.allowClosed && sandboxHandleLeaseAdmissionStates.isClosed(scope)) {
throw new Error(`Daytona sandbox lease ${scope.providerLeaseId} is no longer active.`);
}
const teardownGate = sandboxHandleTeardownGates.current(scope);
if (teardownGate) {
await teardownGate.promise;
if (!options.allowClosed && sandboxHandleLeaseAdmissionStates.isClosed(scope)) {
throw new Error(`Daytona sandbox lease ${scope.providerLeaseId} is no longer active.`);
}
continue;
}
const activityGate = await sandboxHandleActivityGates.begin(scope);
try {
// A teardown can still begin between the initial check above and the
// activity-gate admission. If that happens, back out and wait for the
// teardown to finish instead of proceeding into a race with cleanup.
if (sandboxHandleTeardownGates.current(scope)) {
continue;View on GitHub (pinned to 67001ec6eb)
Solutions
- Stop issuing operations against the lease after release/destroy; cancel queued tasks on teardown.
- If the operation must run, acquire a new lease and re-dispatch.
- Pass options.allowClosed only if the operation is intentionally tolerant of a closed lease (rare).
- Audit for code paths that retain a scope past lease release.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await withSandboxActivityGate(scope, () => op(), { allowClosed: false });
} catch (e) {
if (e instanceof Error && e.message.includes('no longer active')) {
// lease closed at entry; re-acquire or abort this task
}
throw e;
} Prevention
- Cancel queued operations when a lease is released/destroyed.
- Do not retry against the same closed lease; acquire a new one.
- Treat 'no longer active' as terminal for the given providerLeaseId.
When it happens
Trigger: Any sandbox operation routed through withSandboxActivityGate is attempted on a lease that sandboxHandleLeaseAdmissionStates marks closed, with options.allowClosed falsy. This site fires at the top of the while loop before any gate interaction.
Common situations: A concurrent teardown/destroy closed the lease while another caller still holds a reference and issues an operation; a lease was released upstream but a queued task still runs; retry logic re-entering after the lease closed during a wait.
Related errors
- Daytona sandbox ${sandbox.id} is in an unrecoverable error s
- Daytona sandbox handle mismatch: handle ${sandbox.id} does n
- Daytona syncIn requires a provider lease ID.
- Daytona syncOut requires a provider lease ID.
- ${action} timed out: ${result.stderr.trim()}
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/389baf2bdc9a1797.
Report an issue: GitHub.