anomalyco/sst · error · VisibleError

Cannot access the URL because no public ports are exposed.

Error message

Cannot access the URL because no public ports are exposed.

What it means

The Service's `url` getter only has a value when public ports are exposed (or in dev when a dev URL exists). Accessing `.url` in `sst dev` when no dev URL was produced throws this VisibleError.

Source

Thrown at platform/src/components/aws/service-v1.ts:791

              ),
          ),
          command: args.dev?.command,
        })),
      });
    }
  }

  /**
   * The URL of the service.
   *
   * If `public.domain` is set, this is the URL with the custom domain.
   * Otherwise, it's the auto-generated load balancer URL.
   */
  public get url() {
    const errorMessage =
      "Cannot access the URL because no public ports are exposed.";
    if ($dev) {
      if (!this.devUrl) throw new VisibleError(errorMessage);
      return this.devUrl;
    }

    if (!this._url) throw new VisibleError(errorMessage);
    return this._url;
  }

  /**
   * The underlying [resources](/docs/components/#nodes) this component creates.
   */
  public get nodes() {
    const self = this;
    return {
      /**
       * The Amazon ECS Service.
       */
      get service() {
        if ($dev)

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Configure `public` with ports so a URL exists
  2. Guard the access with `this.devUrl` presence or wrap in try/catch
  3. Use `sst.aws.Service`'s URL-unavailable constant pattern: check before accessing

Example fix

// before
export const url = service.url;
// after
export const url = $dev && !service.devUrl ? undefined : service.url;
Defensive patterns

Strategy: try-catch

Validate before calling

// before reading .url in dev
if ($dev && !service.devUrl) {
  console.log("no dev URL; service is not public");
} else {
  const url = service.url;
}

Try / catch

try {
  const url = service.url;
} catch (e) {
  if (e instanceof VisibleError && e.message.includes("no public ports")) {
    const url = undefined; // handle absence
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `service.url` inside `$dev` when the service has no `public` config or the dev server hasn't published a devUrl (e.g. the app didn't print/announce one).

Common situations: Reading `.url` in code that runs during dev mode for a private service; linking the service and reading its URL from another resource in dev.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/f131eb0d0c65eba7. Report an issue: GitHub.