mastra-ai/mastra · error

Sandbox provider "${config.sandbox.provider}" does not suppo

Error message

Sandbox provider "${config.sandbox.provider}" does not support stop.

What it means

The worker deployment exposes a stop() operation, but the underlying sandbox provider adapter does not implement the optional stop capability. The library throws immediately rather than attempting an unsupported provider call.

Source

Thrown at deployers/sandbox/src/worker.ts:397

  return deployment(config, executionId, info?.id ?? config.sandbox.id ?? 'unknown', info?.timeoutAt);
}

function execution(
  config: WorkerExecutionConfig,
  executionId: string,
  sandboxId: string,
  expiresAt?: Date,
): SandboxWorkerExecution {
  const resolvePaths = async () => executionPaths(await config.resolveRemoteDir(), executionId);
  return {
    sandboxId,
    executionId,
    expiresAt,
    status: options => readWorkerStatus(config.sandbox, executionId, resolvePaths, options),
    readOutput: (stream, options) => readOutput(config.sandbox, executionId, resolvePaths, stream, options),
    cancel: () => cancelExecution(config, executionId, resolvePaths),
    stop: async () => {
      if (!config.sandbox.stop) throw new Error(`Sandbox provider "${config.sandbox.provider}" does not support stop.`);
      await config.sandbox.stop();
    },
    destroy: options => destroyWithRetry(config.sandbox, options),
  };
}

function deployment(
  config: WorkerConfig,
  executionId: string,
  sandboxId: string,
  expiresAt?: Date,
): SandboxWorkerDeployment {
  return {
    ...execution(config, executionId, sandboxId, expiresAt),
    relaunch: async options => {
      if (options.executionId === executionId) throw new Error('Relaunch requires a new executionId.');
      validateInput(options.input);
      return createExecution(config, options.executionId, options.input);

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check the provider capabilities before calling stop: `if (sandbox.stop) await sandbox.stop(); else await sandbox.destroy();`
  2. Implement the optional `stop` method on your custom sandbox provider adapter if graceful stop is required.
  3. Use destroy() instead of stop() if hard teardown is acceptable.
  4. Switch to a sandbox provider that supports graceful stop if stop semantics are required.

Example fix

// before
await worker.stop();
// after
if (workerStopSupported) { await worker.stop(); } else { await worker.destroy(); }
Defensive patterns

Strategy: type-guard

Validate before calling

// guard before calling stop
if (typeof sandbox.stop !== 'function') {
  // fall back to destroy or surface capability limitation
}

Type guard

function supportsStop(sandbox) { return typeof sandbox === 'object' && sandbox !== null && typeof sandbox.stop === 'function'; }

Try / catch

try {
  await worker.stop();
} catch (e) {
  if (/does not support stop/.test(e.message)) {
    await worker.destroy(); // graceful stop unavailable; hard teardown
  } else throw e;
}

Prevention

When it happens

Trigger: Calling workerDeployment.stop() (e.g. from attachWorkerDeployment consumers) on a sandbox whose provider object has no stop function — checked via `if (!config.sandbox.stop)`.

Common situations: Using a sandbox provider that only supports destroy (hard teardown) but not graceful stop; custom or minimal provider implementations that omit the optional stop hook; swapping providers in config without updating lifecycle code that assumes stop exists.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/366553e6ebfb549b. Report an issue: GitHub.