{"record":{"id":"1b3e3b1c06189ba0","repo":"mastra-ai/mastra","slug":"sandboxnotreadyerror-sandbox-with-id-this-id","errorCode":null,"errorMessage":"SandboxNotReadyError: sandbox with id '${this.id}' is not ready","messagePattern":"SandboxNotReadyError: sandbox with id '(.+?)' is not ready","errorType":"exception","errorClass":"SandboxNotReadyError","httpStatus":null,"severity":"error","filePath":"packages/core/src/workspace/sandbox/mastra-sandbox.ts","lineNumber":572,"sourceCode":"   * where operations should automatically start the sandbox if needed.\n   *\n   * This is the lazy entry point into the id-keyed getOrCreate contract\n   * described on {@link start}.\n   *\n   * @throws {SandboxNotReadyError} if the sandbox fails to reach 'running' status\n   *\n   * @example\n   * ```typescript\n   * async executeCommand(command: string): Promise<CommandResult> {\n   *   await this.ensureRunning();\n   *   // Now safe to use the sandbox\n   * }\n   * ```\n   */\n  async ensureRunning(): Promise<void> {\n    // Already destroyed — cannot use this sandbox\n    if (this.status === 'destroyed') {\n      throw new SandboxNotReadyError(this.id);\n    }\n    // During teardown the sandbox is still operational (e.g. destroy()\n    // may need to list/kill processes).  Allow operations to proceed\n    // without trying to restart.\n    if (this.status === 'destroying' || this.status === 'stopping') {\n      return;\n    }\n    if (this.status !== 'running') {\n      await this._start();\n    }\n    if (this.status !== 'running') {\n      throw new SandboxNotReadyError(this.id);\n    }\n  }\n\n  /**\n   * Stop the sandbox (wrapper with status management and race-condition safety).\n   *","sourceCodeStart":554,"sourceCodeEnd":590,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/sandbox/mastra-sandbox.ts#L554-L590","documentation":"ensureRunning() throws SandboxNotReadyError when the sandbox has already been destroyed — the instance can no longer execute commands or be restarted. It fails fast instead of attempting operations on a dead sandbox handle.","triggerScenarios":"Calling executeCommand()/ensureRunning() (or the `sandbox` helper) on a sandbox instance after destroy() completed, e.g. keeping a long-lived reference across a shutdown path or using a cached sandbox from a previous run.","commonSituations":"App code caching a sandbox in a module-level variable; a worker holding a sandbox reference that was destroyed by a timeout/cleanup handler; tests that destroy in afterEach but still use it in the last assertion.","solutions":["Create a new sandbox instance instead of reusing the destroyed one.","Check sandbox.status before use and recreate when it is 'destroyed'.","Remove duplicate destroy() calls (e.g. both a timeout handler and afterEach) that kill the sandbox while it is still needed."],"exampleFix":"// before\nawait sandbox.executeCommand('ls');\n// after\nif (sandbox.status === 'destroyed') {\n  sandbox = await createSandbox();\n}\nawait sandbox.executeCommand('ls');","handlingStrategy":"validation","validationCode":"if (sandbox.status === 'destroyed') {\n  sandbox = await createNewSandbox(); // recreate before use\n}","typeGuard":"function isUsable(sandbox: { status: string }): boolean {\n  return sandbox.status !== 'destroyed';\n}","tryCatchPattern":"try {\n  await sandbox.executeCommand(cmd);\n} catch (e) {\n  if (e.name === 'SandboxNotReadyError' && sandbox.status === 'destroyed') {\n    sandbox = await createNewSandbox();\n    return sandbox.executeCommand(cmd);\n  }\n  throw e;\n}","preventionTips":["Never cache sandbox instances across lifetimes; use a factory that recreates on demand.","Check status before operations after any destroy()/stop() path.","Ensure destroy() is called exactly once (single teardown owner) to avoid premature destruction.","Clear references in tests' afterEach so late assertions can't use a destroyed sandbox."],"tags":["sandbox","lifecycle","stale-reference"],"backgroundTag":"sandbox-not-ready","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}