{"record":{"id":"c96ba160ebce254b","repo":"anomalyco/sst","slug":"cannot-access-the-url-because-no-public-ports-are-c96ba1","errorCode":null,"errorMessage":"Cannot access the URL because no public ports are exposed.","messagePattern":"Cannot access the URL because no public ports are exposed\\.","errorType":"exception","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/service.ts","lineNumber":2845,"sourceCode":"              role: taskRole.arn,\n            },\n          });\n        }\n      });\n    }\n  }\n\n  /**\n   * The URL of the service.\n   *\n   * If `public.domain` is set, this is the URL with the custom domain.\n   * Otherwise, it's the auto-generated load balancer URL.\n   */\n  public get url() {\n    const errorMessage =\n      \"Cannot access the URL because no public ports are exposed.\";\n    if (this.dev) {\n      if (!this.devUrl) throw new VisibleError(errorMessage);\n      return this.devUrl;\n    }\n\n    if (!this._url) throw new VisibleError(errorMessage);\n    return this._url;\n  }\n\n  /**\n   * The name of the Cloud Map service. This is useful for service discovery.\n   */\n  public get service() {\n    return all([this.cloudmapNamespace, this.cloudmapService]).apply(\n      ([namespace, service]) => {\n        if (!namespace)\n          throw new VisibleError(\n            `Cannot access the AWS Cloud Map service name for the \"${this._name}\" Service. Cloud Map is not configured for the cluster.`,\n          );\n","sourceCodeStart":2827,"sourceCodeEnd":2863,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/service.ts#L2827-L2863","documentation":"The Service's `url` getter returns the dev URL (in dev mode) or the load balancer URL (in deploy mode). If no public ports were exposed on the Service, neither URL exists, and reading `url` throws this VisibleError to tell you there is nothing to return. It signals a caller accessing `.url` on an internally-only service.","triggerScenarios":"Accessing `myService.url` when the Service was defined without any public ports (no public container ports and no loadBalancer attachment) — in both dev and deploy modes when the corresponding URL (`devUrl`/`_url`) is undefined.","commonSituations":"Linking a backend-only service and blindly reading `.url` in a frontend or another component; removing public ports during a refactor but leaving code that reads the URL; sharing code between services where some expose ports and some don't.","solutions":["Expose at least one public port on the Service so a URL is generated (or attach it to a loadBalancer).","If the service is intentionally private, access it via Cloud Map service discovery (`service.service`) or a linkable resource instead of `.url`.","Wrap the `.url` access in a try/catch for VisibleError, or guard on the component's configuration before reading it."],"exampleFix":"// before\nconst api = new sst.aws.Service(\"Api\", { /* no public ports */ });\nexport const url = api.url;\n// after\nconst api = new sst.aws.Service(\"Api\", {\n  container: { ports: [{ listen: 8080 / http, public: true }] }\n});\nexport const url = api.url;","handlingStrategy":"try-catch","validationCode":"const exposesPublicPort = !!args.container?.ports?.some(p => p.public) || !!args.loadBalancer;\nif (needUrl && !exposesPublicPort) {\n  throw new Error(\"Service must expose a public port before .url can be read\");\n}","typeGuard":"function hasPublicUrl(svc: { url?: string }): boolean {\n  try { return typeof svc.url === \"string\" && svc.url.length > 0; } catch { return false; }\n}","tryCatchPattern":"let url: string;\ntry {\n  url = svc.url;\n} catch (e) {\n  if (e instanceof VisibleError && e.message.includes(\"no public ports are exposed\")) {\n    url = \"\"; // or fall back to internal discovery\n  } else {\n    throw e;\n  }\n}","preventionTips":["Only read `.url` on services that expose at least one public port or an ALB attachment.","For private services use Cloud Map discovery (`svc.service`) or links instead of `.url`.","When removing public ports, grep for `.url` consumers in the same codebase.","Document which services in your stack are public vs internal."],"tags":["aws","ecs","url","public-ports","configuration"],"backgroundTag":"url-not-exposed","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}