@@ -94,7 +94,15 @@ export class E2BSandboxRunner implements SandboxRunner {
9494 private async runApply ( job : SandboxRunRecord , appendLog ?: ( chunk : string ) => void ) : Promise < RunnerOutput > {
9595 const requestedVersion = job . payload . terraformVersion || "1.5.7" ;
9696 const requestedEngine = job . payload . engine || "terraform" ;
97+ const startTime = Date . now ( ) ;
9798 const { sandbox, needsInstall } = await this . createSandbox ( requestedVersion , requestedEngine ) ;
99+
100+ logger . info ( {
101+ sandboxId : sandbox . sandboxId ,
102+ workingDir : job . payload . workingDirectory ,
103+ isDestroy : job . payload . isDestroy ,
104+ } , "Starting apply operation" ) ;
105+
98106 try {
99107 // Install IaC tool if using fallback template
100108 if ( needsInstall ) {
@@ -110,6 +118,8 @@ export class E2BSandboxRunner implements SandboxRunner {
110118
111119 // Run terraform init (with AWS creds if configured for benchmark)
112120 const metadata = job . payload . metadata ;
121+
122+ logger . info ( { sandboxId : sandbox . sandboxId , elapsed : Date . now ( ) - startTime } , "Starting terraform init" ) ;
113123 await this . runTerraformCommand (
114124 sandbox ,
115125 workDir ,
@@ -118,9 +128,11 @@ export class E2BSandboxRunner implements SandboxRunner {
118128 streamLog ,
119129 metadata ,
120130 ) ;
131+ logger . info ( { sandboxId : sandbox . sandboxId , elapsed : Date . now ( ) - startTime } , "Terraform init completed" ) ;
121132
122133 // Run terraform apply/destroy
123134 const applyCommand = job . payload . isDestroy ? "destroy" : "apply" ;
135+ logger . info ( { sandboxId : sandbox . sandboxId , command : applyCommand , elapsed : Date . now ( ) - startTime } , "Starting terraform apply/destroy" ) ;
124136 const applyResult = await this . runTerraformCommand (
125137 sandbox ,
126138 workDir ,
@@ -129,6 +141,7 @@ export class E2BSandboxRunner implements SandboxRunner {
129141 streamLog ,
130142 metadata ,
131143 ) ;
144+ logger . info ( { sandboxId : sandbox . sandboxId , command : applyCommand , elapsed : Date . now ( ) - startTime } , "Terraform apply/destroy completed" ) ;
132145
133146 // Log the apply output for debugging
134147 logger . info ( {
@@ -173,9 +186,30 @@ export class E2BSandboxRunner implements SandboxRunner {
173186 state : stateBase64 ,
174187 } ;
175188
189+ logger . info ( { sandboxId : sandbox . sandboxId , elapsed : Date . now ( ) - startTime } , "Apply operation completed successfully" ) ;
176190 return { logs : logs . join ( "" ) , result } ;
191+ } catch ( err ) {
192+ const elapsed = Date . now ( ) - startTime ;
193+ const errorMessage = err instanceof Error ? err . message : String ( err ) ;
194+
195+ // Log detailed error info for debugging sandbox termination issues
196+ logger . error ( {
197+ sandboxId : sandbox . sandboxId ,
198+ elapsed,
199+ elapsedSeconds : Math . round ( elapsed / 1000 ) ,
200+ errorMessage,
201+ errorType : err instanceof Error ? err . constructor . name : typeof err ,
202+ workingDir : job . payload . workingDirectory ,
203+ } , "Apply operation failed - sandbox may have been terminated" ) ;
204+
205+ throw err ;
177206 } finally {
178- await sandbox . kill ( ) ;
207+ try {
208+ await sandbox . kill ( ) ;
209+ } catch ( killErr ) {
210+ // Sandbox may already be dead, that's fine
211+ logger . debug ( { killErr } , "Failed to kill sandbox (may already be terminated)" ) ;
212+ }
179213 }
180214 }
181215
@@ -201,11 +235,19 @@ export class E2BSandboxRunner implements SandboxRunner {
201235 logger . warn ( { templateId, engine, version } , "no pre-built template found, will install at runtime" ) ;
202236 }
203237
204- // Extend sandbox lifetime to 30 minutes for long-running benchmarks
238+ // Extend sandbox lifetime to 1 hour for long-running benchmarks (EKS, etc.)
205239 // Default is 5 minutes which isn't enough for large terraform applies
206- const sandboxTimeoutSeconds = 30 * 60 ; // 30 minutes
240+ // Pro tier supports up to 24 hours, Hobby up to 1 hour
241+ const sandboxTimeoutSeconds = 60 * 60 ; // 1 hour
242+
243+ // NOTE: CPU/memory are set at template BUILD time, not runtime
244+ // See templates/build-all.ts for resource configuration (8 CPU, 8GB RAM)
245+
246+ logger . info ( {
247+ templateId,
248+ timeoutSeconds : sandboxTimeoutSeconds ,
249+ } , "creating E2B sandbox" ) ;
207250
208- logger . info ( { templateId, timeoutSeconds : sandboxTimeoutSeconds } , "creating E2B sandbox" ) ;
209251 const sandbox = await Sandbox . create ( templateId , {
210252 apiKey : this . options . apiKey ,
211253 timeoutMs : sandboxTimeoutSeconds * 1000 ,
@@ -380,9 +422,18 @@ export class E2BSandboxRunner implements SandboxRunner {
380422 appendLog ?.( chunk ) ;
381423 } ;
382424
383- // Use long timeout for benchmarks (30 minutes) - some operations like 10k resources take a while
384- // Set to 0 to disable timeout entirely if needed
385- const timeoutMs = 30 * 60 * 1000 ; // 30 minutes
425+ // Use long timeout for benchmarks (1 hour) - EKS and large operations need this
426+ // Pro tier supports up to 24 hours, Hobby up to 1 hour
427+ const timeoutMs = 60 * 60 * 1000 ; // 1 hour
428+
429+ // Explicitly extend sandbox lifetime before running long commands
430+ // This ensures the sandbox won't be killed mid-operation
431+ try {
432+ await Sandbox . setTimeout ( sandbox . sandboxId , timeoutMs , { apiKey : this . options . apiKey } ) ;
433+ logger . info ( { sandboxId : sandbox . sandboxId , timeoutMs } , "Extended sandbox timeout before command" ) ;
434+ } catch ( err ) {
435+ logger . warn ( { err, sandboxId : sandbox . sandboxId } , "Failed to extend sandbox timeout (continuing anyway)" ) ;
436+ }
386437
387438 const result = await sandbox . commands . run ( cmdStr , {
388439 cwd,
0 commit comments