mastra-ai/mastra · critical

Sandbox provider '${sandbox.provider}' does not support exec

Error message

Sandbox provider '${sandbox.provider}' does not support executeCommand, which is required to run git and filesystem operations in a session.

What it means

requireExec narrows a WorkspaceSandbox to an ExecutableSandbox by checking that executeCommand is a function. If the configured sandbox provider lacks executeCommand, materialization throws immediately rather than letting git/filesystem operations silently no-op with an undefined exit code, since session setup and teardown depend on running real commands.

Source

Thrown at mastracode/factory/src/sandbox/materialization.ts:40

   * these helpers read: core's `CommandResult` also carries `success` and
   * `executionTimeMs`, and asking for them would reject test doubles that
   * report exactly what the helpers consume.
   */
  executeCommand(command: string, args?: string[], options?: ExecuteCommandOptions): Promise<SandboxCommandResult>;
};

/**
 * Narrow a sandbox to one that can run commands, or fail saying which
 * capability is missing.
 *
 * Callers hold a `WorkspaceSandbox`, whose `executeCommand` is optional.
 * Optional-chaining past it would hand every caller `undefined` where it
 * expects an exit code, turning a misconfigured provider into a git command
 * that silently did nothing.
 */
export function requireExec(sandbox: WorkspaceSandbox): ExecutableSandbox {
  if (typeof sandbox.executeCommand !== 'function') {
    throw new Error(
      `Sandbox provider '${sandbox.provider}' does not support executeCommand, which is required to run git and filesystem operations in a session.`,
    );
  }
  return sandbox as ExecutableSandbox;
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Configure a sandbox provider that implements executeCommand (an executing provider such as a container/VM/local shell).
  2. If using a custom provider, implement executeCommand(command) returning { stdout, stderr, exitCode }.
  3. Check the provider name in your factory/sandbox config for typos that fall back to a non-executing default.
  4. Upgrade/downgrade so the provider matches the WorkspaceSandbox interface expected by this version.

Example fix

// before
sandbox: { provider: 'readonly-fs' } // no executeCommand
// after
sandbox: { provider: 'docker', image: 'workspace:latest' } // provider with executeCommand support
Defensive patterns

Strategy: type-guard

Validate before calling

function assertExecutable(sandbox) {
  if (typeof sandbox.executeCommand !== 'function') {
    throw new Error(`Provider '${sandbox.provider}' cannot run sessions; choose an executing provider.`);
  }
}
assertExecutable(configuredSandbox); // before session create/teardown

Type guard

interface ExecutableSandbox { executeCommand(cmd: string): Promise<{ stdout: string; stderr: string; exitCode: number }> }
function isExecutableSandbox(s: WorkspaceSandbox): s is WorkspaceSandbox & ExecutableSandbox {
  return typeof (s as Partial<ExecutableSandbox>).executeCommand === 'function';
}

Try / catch

try {
  await teardownSessionSandbox(session);
} catch (e) {
  if (/does not support executeCommand/.test(e.message)) {
    logger.error('Misconfigured sandbox provider; skipping command-based teardown', { provider: session.sandbox.provider });
    return; // or re-create session with an executing provider
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling requireExec (directly or via #teardownSessionSandbox during session teardown) with a sandbox whose provider is read-only or non-executing — e.g. a provider configured with an exec-disabled or command-less mode, or passing a custom WorkspaceSandbox implementation that never defined executeCommand.

Common situations: Configuring a storage/preview-only sandbox provider where an executing one (docker/VM/shell) is required; a custom provider implementing only the file-transfer surface; a version change where executeCommand was renamed or made optional on the interface.

Related errors


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