From 342e2e98d762da31ce77e97d1dd5f3aaf5834575 Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 19:20:17 +0000 Subject: [PATCH 1/3] fix(sandbox): add logging for session resets Log when the sandbox hint is dropped (profile mismatch), when a hinted sandbox cannot be restored (Sandbox.get failure), and when an unavailable sandbox triggers recreation. All three paths were previously silent, making it impossible to diagnose unexpected session resets from Sentry after the fact. Co-Authored-By: claude-sonnet-4-5 Co-authored-by: David Cramer --- packages/junior/src/chat/sandbox/session.ts | 32 +++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/junior/src/chat/sandbox/session.ts b/packages/junior/src/chat/sandbox/session.ts index 0ef60e34..d1da5f2e 100644 --- a/packages/junior/src/chat/sandbox/session.ts +++ b/packages/junior/src/chat/sandbox/session.ts @@ -1,7 +1,7 @@ import { randomUUID } from "node:crypto"; import { Sandbox, type NetworkPolicy } from "@vercel/sandbox"; import { createBashTool } from "bash-tool"; -import { setSpanAttributes, withSpan, type LogContext } from "@/chat/logging"; +import { logInfo, logWarn, setSpanAttributes, withSpan, type LogContext } from "@/chat/logging"; import { getVercelSandboxCredentials } from "@/chat/sandbox/credentials"; import { isAlreadyExistsError, @@ -308,6 +308,12 @@ export function createSandboxSessionManager(options?: { "app.sandbox.recovery.attempted": true, "app.sandbox.recovery.source": source, }); + logWarn( + "sandbox_unavailable_recreating", + traceContext, + { "app.sandbox.recovery.source": source }, + "Sandbox unavailable; recreating", + ); clearSession(); const replacement = await createFreshSandbox(); setSpanAttributes({ @@ -491,6 +497,19 @@ export function createSandboxSessionManager(options?: { ? { "app.sandbox.current_profile_hash": dependencyProfileHash } : {}), }); + logInfo( + "sandbox_hint_discarded_profile_mismatch", + traceContext, + { + ...(options?.sandboxDependencyProfileHash + ? { "app.sandbox.previous_profile_hash": options.sandboxDependencyProfileHash } + : {}), + ...(dependencyProfileHash + ? { "app.sandbox.current_profile_hash": dependencyProfileHash } + : {}), + }, + "Dependency profile changed; discarding sandbox hint and creating fresh session", + ); sandboxIdHint = undefined; }; @@ -537,7 +556,16 @@ export function createSandboxSessionManager(options?: { } as Parameters[0]), ), ); - } catch { + } catch (error) { + logWarn( + "sandbox_restore_hint_failed", + traceContext, + { + "app.sandbox.hint_id": sandboxIdHint, + "app.sandbox.error": error instanceof Error ? error.message : String(error), + }, + "Failed to restore sandbox from hint; will create fresh session", + ); return null; } From d4ca56b8c9513f4dcd76efb6fd17e38e8520344a Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 19:33:26 +0000 Subject: [PATCH 2/3] fix(sandbox): drop redundant log attributes already on active span recovery.source and the profile hash attrs are set on the active sandbox.acquire span via setSpanAttributes immediately above each log call. No need to duplicate them in the log record. Co-authored-by: David Cramer --- packages/junior/src/chat/sandbox/session.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/junior/src/chat/sandbox/session.ts b/packages/junior/src/chat/sandbox/session.ts index d1da5f2e..d136fb46 100644 --- a/packages/junior/src/chat/sandbox/session.ts +++ b/packages/junior/src/chat/sandbox/session.ts @@ -311,7 +311,7 @@ export function createSandboxSessionManager(options?: { logWarn( "sandbox_unavailable_recreating", traceContext, - { "app.sandbox.recovery.source": source }, + {}, "Sandbox unavailable; recreating", ); clearSession(); @@ -500,14 +500,7 @@ export function createSandboxSessionManager(options?: { logInfo( "sandbox_hint_discarded_profile_mismatch", traceContext, - { - ...(options?.sandboxDependencyProfileHash - ? { "app.sandbox.previous_profile_hash": options.sandboxDependencyProfileHash } - : {}), - ...(dependencyProfileHash - ? { "app.sandbox.current_profile_hash": dependencyProfileHash } - : {}), - }, + {}, "Dependency profile changed; discarding sandbox hint and creating fresh session", ); sandboxIdHint = undefined; From 80a913bfc0657224874037ef35d0bc384f893374 Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 19:42:48 +0000 Subject: [PATCH 3/3] fix(sandbox): restore diagnostic attributes to log calls Log records should carry the key attrs inline so they're debuggable without jumping to the correlated span. Re-adds recovery.source to sandbox_unavailable_recreating and the profile hashes to sandbox_hint_discarded_profile_mismatch. --- packages/junior/src/chat/sandbox/session.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/junior/src/chat/sandbox/session.ts b/packages/junior/src/chat/sandbox/session.ts index d136fb46..d1da5f2e 100644 --- a/packages/junior/src/chat/sandbox/session.ts +++ b/packages/junior/src/chat/sandbox/session.ts @@ -311,7 +311,7 @@ export function createSandboxSessionManager(options?: { logWarn( "sandbox_unavailable_recreating", traceContext, - {}, + { "app.sandbox.recovery.source": source }, "Sandbox unavailable; recreating", ); clearSession(); @@ -500,7 +500,14 @@ export function createSandboxSessionManager(options?: { logInfo( "sandbox_hint_discarded_profile_mismatch", traceContext, - {}, + { + ...(options?.sandboxDependencyProfileHash + ? { "app.sandbox.previous_profile_hash": options.sandboxDependencyProfileHash } + : {}), + ...(dependencyProfileHash + ? { "app.sandbox.current_profile_hash": dependencyProfileHash } + : {}), + }, "Dependency profile changed; discarding sandbox hint and creating fresh session", ); sandboxIdHint = undefined;