vercel/ai · error · HarnessCapabilityUnsupportedError

Port ${options.port} is not exposed on this sandbox. Exposed

Error message

Port ${options.port} is not exposed on this sandbox. Exposed ports: [${exposedPorts.join(', ')}].

What it means

Vercel sandbox sessions can only expose ports declared when the sandbox was created. getPortEndpoint validates the requested port against the session's exposed ports list and throws HarnessCapabilityUnsupportedError when the port was never exposed, listing the ports that are available.

Source

Thrown at packages/sandbox-vercel/src/vercel-network-sandbox-session.ts:56

      sandbox: input.sandbox,
    });
  }

  get ports(): ReadonlyArray<number> {
    return this.sandbox.routes.map(route => route.port);
  }

  restricted(): SandboxSession {
    return new VercelSandboxSession(this.sandbox);
  }

  getPortEndpoint = async (options: {
    port: number;
    protocol?: 'http' | 'https' | 'ws';
  }): Promise<HarnessV1PortEndpoint> => {
    const exposedPorts = this.ports;
    if (!exposedPorts.includes(options.port)) {
      throw new HarnessCapabilityUnsupportedError({
        harnessId: VERCEL_PROVIDER_ID,
        message: `Port ${options.port} is not exposed on this sandbox. Exposed ports: [${exposedPorts.join(', ')}].`,
      });
    }
    const protocol = options.protocol ?? 'https';
    const url = new URL(this.sandbox.domain(options.port));
    const isSecure = url.protocol === 'https:';
    switch (protocol) {
      case 'http':
        url.protocol = isSecure ? 'https:' : 'http:';
        break;
      case 'https':
        url.protocol = 'https:';
        break;
      case 'ws':
        url.protocol = isSecure ? 'wss:' : 'ws:';
        break;
    }

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Add the required port to the sandbox's exposed ports when creating it
  2. Request one of the ports listed in the error message
  3. Align your server's listening port with an exposed port
  4. Catch HarnessCapabilityUnsupportedError and surface the available ports

Example fix

// before
const sandbox = vercelSandbox({});
await sandbox.getPortEndpoint({ port: 3000 });
// after
const sandbox = vercelSandbox({ ports: [3000] });
await sandbox.getPortEndpoint({ port: 3000 });
Defensive patterns

Strategy: validation

Validate before calling

function assertPortExposed(session, port) {
  const exposed = session.ports ?? [];
  if (!exposed.includes(port)) {
    throw new Error(`Port ${port} not exposed. Exposed ports: [${exposed.join(', ')}].`);
  }
}
// call before getPortEndpoint

Type guard

function isPortNotExposed(e) {
  return typeof e === 'object' && e !== null && e.constructor?.name === 'HarnessCapabilityUnsupportedError' && /not exposed/.test(String(e.message));
}

Try / catch

try {
  endpoint = await session.getPortEndpoint({ port });
} catch (e) {
  if (isPortNotExposed(e)) {
    throw new Error(`Configure ports [${port}] when creating the sandbox. ${e.message}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling getPortEndpoint({ port: N }) where N is not in the sandbox's configured exposed ports (this.ports) — e.g. requesting 3000 when only 8080 was exposed.

Common situations: Sandbox created without the port the app listens on; default-port mismatch (app binds 3000 but sandbox exposes 8080); typos in port configuration.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/764bb3daa4033ea5. Report an issue: GitHub.