{"record":{"id":"3f274347f1def5ac","repo":"mastra-ai/mastra","slug":"sandbox-provider-sandbox-provider-did-not-exp","errorCode":null,"errorMessage":"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}]`).","messagePattern":"Sandbox provider \"(.+?)\" did not expose a public URL for port (.+?)\\. Make sure the port is declared when constructing the sandbox \\(e\\.g\\. `ports: \\[(.+?)\\]`\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"deployers/sandbox/src/client/index.ts","lineNumber":122,"sourceCode":"\n  if (!wake) {\n    // Resolve without starting the sandbox (starting can resume billing).\n    const url = supportsNetworking(sandbox) ? await sandbox.networking.getPortUrl(port) : null;\n    if (!url) {\n      return handle(null, 'stopped');\n    }\n    const healthy = await waitForHealthy(url, { path: healthCheckPath, timeoutMs: 3_000, intervalMs: 1_000 });\n    return handle(url, healthy ? 'running' : 'stopped');\n  }\n\n  await sandbox.start?.();\n\n  if (!supportsNetworking(sandbox)) {\n    throw new Error(`Sandbox provider \"${sandbox.provider}\" does not support networking (public port URLs).`);\n  }\n  const url = await sandbox.networking.getPortUrl(port);\n  if (!url) {\n    throw new Error(\n      `Sandbox provider \"${sandbox.provider}\" did not expose a public URL for port ${port}. ` +\n        `Make sure the port is declared when constructing the sandbox (e.g. \\`ports: [${port}]\\`).`,\n    );\n  }\n\n  // Some providers (e.g. Vercel) restore the filesystem but not processes on\n  // resume, while others (e.g. E2B) resume processes too — relaunch the server\n  // from the recorded launch script only when it is not answering.\n  let healthy = await waitForHealthy(url, { path: healthCheckPath, timeoutMs: 3_000, intervalMs: 1_000 });\n  if (!healthy) {\n    const remoteDir = await resolveRemoteDir(sandbox, options.remoteDir);\n    await killPreviousServer(sandbox, remoteDir);\n    await launchServer(sandbox, remoteDir);\n    healthy = await waitForHealthy(url, { path: healthCheckPath, timeoutMs: healthCheckTimeoutMs, intervalMs: 1_000 });\n  }\n  if (!healthy) {\n    const log = await resolveRemoteDir(sandbox, options.remoteDir)\n      .then(dir => tailServerLog(sandbox, dir))","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/deployers/sandbox/src/client/index.ts#L104-L140","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Add the port to the sandbox constructor's `ports` array (e.g. `new Sandbox({ ports: [8788] })`)","Ensure the PORT passed to deployToSandbox/getDeployment matches a declared port","Recreate/restart the sandbox so the provider provisions the port URL","Check provider docs for how public URLs are allocated (some only allocate declared ports at creation time)"],"exampleFix":"// before\nconst sandbox = new Sandbox({ provider: 'cloudflare', ports: [8787] });\nawait getDeployment(sandbox, { port: 8788 });\n// after\nconst sandbox = new Sandbox({ provider: 'cloudflare', ports: [8787, 8788] });\nawait getDeployment(sandbox, { port: 8788 });","handlingStrategy":"validation","validationCode":"import { supportsNetworking } from '@mastra/deployers-sandbox/client';\nif (!supportsNetworking(sandbox)) throw new Error('provider lacks networking');\n// ports must include the deploy port before creating the sandbox\nif (!ports.includes(port)) throw new Error(`declare ports: [${port}]`);","typeGuard":"function hasNetworking(s: Sandbox): s is Sandbox & { networking: { getPortUrl(p: number): Promise<string | null> } } {\n  return typeof (s as any).networking?.getPortUrl === 'function';\n}","tryCatchPattern":null,"preventionTips":["Always declare every port you will deploy on in the sandbox constructor's ports option","Keep the deploy PORT constant in one place shared with sandbox config","Feature-check supportsNetworking before choosing the sandbox deploy path"],"tags":["sandbox","networking","port-url","deployment"],"backgroundTag":"port-not-exposed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}