Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/improve-session-initialization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cloudflare/sandbox': patch
---

Improve session initialization to check storage before creating new session
7 changes: 3 additions & 4 deletions packages/sandbox-container/src/services/session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@ export class SessionManager {
success: false,
error: {
message: `Session '${options.id}' already exists`,
code: ErrorCode.INTERNAL_ERROR,
code: ErrorCode.RESOURCE_BUSY,
details: {
sessionId: options.id,
originalError: 'Session already exists'
} satisfies InternalErrorContext
sessionId: options.id
}
}
};
}
Expand Down
53 changes: 26 additions & 27 deletions packages/sandbox/src/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -994,39 +994,38 @@ export class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
* we reuse it instead of trying to create a new one.
*/
private async ensureDefaultSession(): Promise<string> {
if (!this.defaultSession) {
const sessionId = `sandbox-${this.sandboxName || 'default'}`;
const sessionId = `sandbox-${this.sandboxName || 'default'}`;

try {
// Try to create session in container
await this.client.utils.createSession({
id: sessionId,
env: this.envVars || {},
cwd: '/workspace'
});
// Fast path: session already initialized in this instance
if (this.defaultSession === sessionId) {
return this.defaultSession;
}

// Create session in container
try {
await this.client.utils.createSession({
id: sessionId,
env: this.envVars || {},
cwd: '/workspace'
});

this.defaultSession = sessionId;
await this.ctx.storage.put('defaultSession', sessionId);
this.logger.debug('Default session initialized', { sessionId });
} catch (error: unknown) {
// Session may already exist (e.g., after hot reload or concurrent request)
if (error instanceof Error && error.message.includes('already exists')) {
this.logger.debug(
'Session exists in container but not in DO state, syncing',
{ sessionId }
);
this.defaultSession = sessionId;
// Persist to storage so it survives hot reloads
await this.ctx.storage.put('defaultSession', sessionId);
this.logger.debug('Default session initialized', { sessionId });
} catch (error: unknown) {
// If session already exists (e.g., after hot reload), reuse it
if (
error instanceof Error &&
error.message.includes('already exists')
) {
this.logger.debug('Reusing existing session after reload', {
sessionId
});
this.defaultSession = sessionId;
// Persist to storage in case it wasn't saved before
await this.ctx.storage.put('defaultSession', sessionId);
} else {
// Re-throw other errors
throw error;
}
} else {
throw error;
}
}

return this.defaultSession;
}

Expand Down
Loading