Files
PaperClipAI/server
Nicky LeachandPaperclip e1f245a660 fix(server): recover sandbox leases stranded active after a restart (#13515)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The server starts and stops provider sandboxes through environment
leases
> - A restart can leave a terminal run with an `active` lease
> - The normal orphan recovery path cannot find that lease after the run
ends
> - This pull request adds a bounded sweep that changes the stranded
lease to `pending_cleanup`
> - The existing cleanup sweep then stops the provider sandbox on the
same heartbeat tick
> - The benefit is that stranded sandboxes stop and do not continue to
create provider cost

## Linked Issues or Issue Description

**What happened?**

A restart can occur after the server writes a terminal run status but
before it releases the related environment lease. The lease then stays
`active`, and later recovery does not select it. A second path skips the
lease when its environment row does not exist.

**Expected behavior**

The heartbeat recovery path must find an `active` lease that no live run
can release. It must move that lease to `pending_cleanup`, and the
cleanup sweep must stop the provider sandbox.

**Steps to reproduce**

1. Start a run that owns a provider sandbox lease.
2. End the run and stop the server between the run-status write and the
lease-release write.
3. Restart the server and allow the heartbeat recovery sweep to run.
4. Confirm that the lease reaches `pending_cleanup` and the provider
sandbox receives a stop request.

**Paperclip version or commit**

This pull request targets the current `master` branch at the base commit
used for review.

**Deployment mode**

The change applies to local development and server deployments.

**Installation method**

Built from source with the repository test commands.

**Agent adapter(s) involved**

Not adapter-specific. The change applies to core heartbeat recovery.

**Database mode**

The change uses the existing database tables. It adds no migration.

## What Changed

- Add `sweepOrphanedActiveLeases()` to heartbeat recovery.
- Select only stale `active` leases that have no live run owner.
- Skip leases with a different live lease for the same provider
resource.
- Preserve retained leases and write a failure reason for recovered
leases.
- Limit each sweep to 20 rows.
- Run the recovery sweep before the pending-cleanup sweep.
- Add focused tests for the recovery guards and same-tick cleanup.

## Verification

- `pnpm vitest run
server/src/__tests__/heartbeat-orphaned-active-lease-sweep.test.ts` — 10
tests pass.
- `pnpm vitest run
server/src/__tests__/heartbeat-pending-cleanup-sweep.test.ts` — 22 tests
pass.
- `pnpm --filter @paperclipai/server typecheck` — exits 0.
- The complete CI suite remains the final check for the repository.

## Risks

The sweep changes only stale `active` leases that no live run can
release. The stale threshold, live-resource guard, retained-lease guard,
and page limit reduce false recovery. The change adds no endpoint,
schema change, or migration.

## Model Used

OpenAI Codex, GPT-5, tool-enabled coding agent with repository
inspection, GitHub CLI, and test execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-15 21:52:02 -07:00
..