mastra-ai/mastra · error

Sandbox provider "${sandbox.provider}" did not expose a publ

Error message

Sandbox provider "${sandbox.provider}" did not expose a public URL for port ${port}. Make sure the port is declared when constructing the sandbox (e.g. `ports: [${port}]`).

What it means

Thrown by getDeployment when a sandbox provider's networking API returns no public URL for the requested port. The library requires the port to be declared on the sandbox so the provider allocates/proxies a public endpoint. Without it, the deployer cannot reach the Mastra server.

Source

Thrown at deployers/sandbox/src/client/index.ts:122

  if (!wake) {
    // Resolve without starting the sandbox (starting can resume billing).
    const url = supportsNetworking(sandbox) ? await sandbox.networking.getPortUrl(port) : null;
    if (!url) {
      return handle(null, 'stopped');
    }
    const healthy = await waitForHealthy(url, { path: healthCheckPath, timeoutMs: 3_000, intervalMs: 1_000 });
    return handle(url, healthy ? 'running' : 'stopped');
  }

  await sandbox.start?.();

  if (!supportsNetworking(sandbox)) {
    throw new Error(`Sandbox provider "${sandbox.provider}" does not support networking (public port URLs).`);
  }
  const url = await sandbox.networking.getPortUrl(port);
  if (!url) {
    throw new Error(
      `Sandbox provider "${sandbox.provider}" did not expose a public URL for port ${port}. ` +
        `Make sure the port is declared when constructing the sandbox (e.g. \`ports: [${port}]\`).`,
    );
  }

  // Some providers (e.g. Vercel) restore the filesystem but not processes on
  // resume, while others (e.g. E2B) resume processes too — relaunch the server
  // from the recorded launch script only when it is not answering.
  let healthy = await waitForHealthy(url, { path: healthCheckPath, timeoutMs: 3_000, intervalMs: 1_000 });
  if (!healthy) {
    const remoteDir = await resolveRemoteDir(sandbox, options.remoteDir);
    await killPreviousServer(sandbox, remoteDir);
    await launchServer(sandbox, remoteDir);
    healthy = await waitForHealthy(url, { path: healthCheckPath, timeoutMs: healthCheckTimeoutMs, intervalMs: 1_000 });
  }
  if (!healthy) {
    const log = await resolveRemoteDir(sandbox, options.remoteDir)
      .then(dir => tailServerLog(sandbox, dir))

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Add the port to the sandbox constructor's `ports` array (e.g. `new Sandbox({ ports: [8788] })`)
  2. Ensure the PORT passed to deployToSandbox/getDeployment matches a declared port
  3. Recreate/restart the sandbox so the provider provisions the port URL
  4. Check provider docs for how public URLs are allocated (some only allocate declared ports at creation time)

Example fix

// before
const sandbox = new Sandbox({ provider: 'cloudflare', ports: [8787] });
await getDeployment(sandbox, { port: 8788 });
// after
const sandbox = new Sandbox({ provider: 'cloudflare', ports: [8787, 8788] });
await getDeployment(sandbox, { port: 8788 });
Defensive patterns

Strategy: validation

Validate before calling

import { supportsNetworking } from '@mastra/deployers-sandbox/client';
if (!supportsNetworking(sandbox)) throw new Error('provider lacks networking');
// ports must include the deploy port before creating the sandbox
if (!ports.includes(port)) throw new Error(`declare ports: [${port}]`);

Type guard

function hasNetworking(s: Sandbox): s is Sandbox & { networking: { getPortUrl(p: number): Promise<string | null> } } {
  return typeof (s as any).networking?.getPortUrl === 'function';
}

Prevention

When it happens

Trigger: Calling getDeployment (e.g. `mastra deploy` to a sandbox target) while the sandbox instance was constructed without the requested port in its `ports` option, or the provider failed to provision the URL for a declared port (returns null from getPortUrl).

Common situations: Passing a non-default PORT to the deployer but constructing the sandbox with `ports: [8788]` only; copying provider config between providers where one declares ports implicitly; a provider that silently skips port allocation until the sandbox is running and the port is pre-declared.

Related errors


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