fix(sandbox): recover git/daemon proxy when preview handle is stale#3606
fix(sandbox): recover git/daemon proxy when preview handle is stale#3606guitavano wants to merge 1 commit into
Conversation
Preview gateway traffic could stay live while mesh daemon/git paths still returned 410 on stale handles. Resurrect or adopt the live claim before surfacing gone, and self-heal the publish dialog on 410. Co-authored-by: Cursor <cursoragent@cursor.com>
🧪 BenchmarkShould we run the Virtual MCP strategy benchmark for this PR? React with 👍 to run the benchmark.
Benchmark will run on the next push after you react. |
Release OptionsSuggested: Patch ( React with an emoji to override the release type:
Current version:
|
There was a problem hiding this comment.
1 issue found across 4 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/mesh/src/api/routes/sandbox-proxy.ts">
<violation number="1" location="apps/mesh/src/api/routes/sandbox-proxy.ts:202">
P1: `adoptLiveClaim` errors are unhandled in `proxyDaemon`, which can turn a recoverable 404 path into a 500 response.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| const adopted = await runner.adoptLiveClaim?.( | ||
| { userId, projectRef }, | ||
| claimName, | ||
| ); |
There was a problem hiding this comment.
P1: adoptLiveClaim errors are unhandled in proxyDaemon, which can turn a recoverable 404 path into a 500 response.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/api/routes/sandbox-proxy.ts, line 202:
<comment>`adoptLiveClaim` errors are unhandled in `proxyDaemon`, which can turn a recoverable 404 path into a 500 response.</comment>
<file context>
@@ -193,14 +199,32 @@ async function proxyDaemon(
- },
- 410,
- SANDBOX_PROXY_CACHE_HEADERS,
+ const adopted = await runner.adoptLiveClaim?.(
+ { userId, projectRef },
+ claimName,
</file context>
| const adopted = await runner.adoptLiveClaim?.( | |
| { userId, projectRef }, | |
| claimName, | |
| ); | |
| let adopted = false; | |
| try { | |
| adopted = | |
| (await runner.adoptLiveClaim?.({ userId, projectRef }, claimName)) ?? | |
| false; | |
| } catch { | |
| adopted = false; | |
| } |
Architectural noteThe preview gateway cannot be out of sync with the daemon proxy — preview traffic is served by the daemon (port 9000, reverse-proxying to the dev server). Both paths must resolve the same handle to the same live pod. What was happening in prod:
The handle is deterministic ( This PR aligns the daemon/git proxy recovery path with what preview already does: resurrect from state-store, adopt the live K8s claim, then retry — so gateway and daemon proxy always converge on the same handle → same pod. |
Summary
proxyDaemonRequestbefore returning 404, matching the recovery path preview already usesadoptLiveClaimbefore mapping 404 → 410 GoneSANDBOX_STARTonce when git APIs return 410Fixes the production issue where preview stays up but
GET /api/:org/sandbox/:virtualMcpId/:branch/git/statusreturns 410 with "Sandbox handle is gone".Test plan
git/status,git/diff, and publish still work on a healthy sandboxMade with Cursor
Summary by cubic
Recover git/daemon proxy when a sandbox handle is stale so Save changes and Publish keep working while preview is live. The UI now self-heals once before surfacing 410 Gone.
adoptLiveClaimand retry once; only then map 404 → 410.adoptLiveClaimto the agent sandbox provider and mirrored preview resurrection inproxyDaemonRequest, including retries after 401 or port-forward failures.git/statusandgit/diffpass{ userId, projectRef }to enable adoption and retry.SANDBOX_STARTviauseSandboxStart(@decocms/mesh-sdk+SELF_MCP_ALIAS_ID), then retries loading changes.Written for commit 08894ab. Summary will update on new commits.