firecrawl/open-lovable · error · Error

No active sandbox

Error message

No active sandbox

What it means

E2BProvider throws 'No active sandbox' when a lifecycle method (runCommand) is called before a sandbox instance exists. this.sandbox is only assigned by createSandbox() (or reconnect()); every operation guards on it and fails fast. It signals a programming-order mistake, not a sandbox runtime failure.

Source

Thrown at lib/sandbox/providers/e2b-provider.ts:75

        createdAt: new Date()
      };

      // Set extended timeout on the sandbox instance if method available
      if (typeof this.sandbox.setTimeout === 'function') {
        this.sandbox.setTimeout(appConfig.e2b.timeoutMs);
      }

      return this.sandboxInfo;

    } catch (error) {
      console.error('[E2BProvider] Error creating sandbox:', error);
      throw error;
    }
  }

  async runCommand(command: string): Promise<CommandResult> {
    if (!this.sandbox) {
      throw new Error('No active sandbox');
    }

    
    const result = await this.sandbox.runCode(`
      import subprocess
      import os

      os.chdir('/home/user/app')
      result = subprocess.run(${JSON.stringify(command.split(' '))}, 
                            capture_output=True, 
                            text=True, 
                            shell=False)

      print("STDOUT:")
      print(result.stdout)
      if result.stderr:
          print("\\nSTDERR:")
          print(result.stderr)

View on GitHub (pinned to 69bd93bae7)

Solutions

  1. Call `await provider.createSandbox()` before any runCommand/writeFile/readFile/listFiles/installPackages/setupViteApp/restartViteServer call
  2. Check `if (!provider.hasActiveSandbox?.()) await provider.createSandbox()` at the start of each request
  3. If the sandbox expired, reconnect via `await provider.reconnect(sandboxId)` or recreate it
  4. Wrap provider usage in a lazy-init helper that creates the sandbox once and reuses it

Example fix

// before
const provider = new E2BProvider();
await provider.runCommand('ls');
// after
const provider = new E2BProvider();
await provider.createSandbox();
await provider.runCommand('ls');
Defensive patterns

Strategy: validation

Validate before calling

if (!provider.sandbox) {
  await provider.createSandbox();
}
await provider.runCommand(command);

Type guard

function hasActiveSandbox(p): p is E2BProvider & { sandbox: NonNullable<E2BProvider['sandbox']> } {
  return p.sandbox != null;
}

Try / catch

try {
  await provider.runCommand(cmd);
} catch (e) {
  if (e instanceof Error && e.message === 'No active sandbox') {
    await provider.createSandbox();
    return provider.runCommand(cmd);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling provider.runCommand(cmd) without first awaiting provider.createSandbox(); using a freshly constructed E2BProvider; calling after a sandbox expired/crashed and this.sandbox was reset without recreation.

Common situations: Instantiating the provider in a route handler and calling runCommand immediately; sandbox idled out mid-session (E2B timeouts) so the reference is stale/null; race where two requests share one provider and one closed it; forgetting createSandbox() after a refactor.

Related errors


AI-assisted analysis of firecrawl/open-lovable@69bd93bae7 (2026-08-28). Data as JSON: /api/errors/577ed8a27c315a7a. Report an issue: GitHub.