anomalyco/sst · error · VisibleError

Cannot access `nodes.taskDefinition` in dev mode.

Error message

Cannot access `nodes.taskDefinition` in dev mode.

What it means

The Service component's `nodes` getter exposes raw Pulumi resources it creates. In `sst dev` mode the Service runs as a live dev process against the cluster and the ECS Task Definition resource is never created, so accessing `nodes.taskDefinition` would return `undefined`. SST throws this VisibleError to fail fast instead of letting downstream code operate on a missing resource.

Source

Thrown at platform/src/components/aws/service.ts:2898

      get service() {
        if (self.dev)
          throw new VisibleError("Cannot access `nodes.service` in dev mode.");
        return self._service!;
      },
      /**
       * The Amazon ECS Execution Role.
       */
      executionRole: this.executionRole,
      /**
       * The Amazon ECS Task Role.
       */
      taskRole: this.taskRole,
      /**
       * The Amazon ECS Task Definition.
       */
      get taskDefinition() {
        if (self.dev)
          throw new VisibleError(
            "Cannot access `nodes.taskDefinition` in dev mode.",
          );
        return self.taskDefinition!;
      },
      /**
       * The Amazon Elastic Load Balancer.
       */
      get loadBalancer() {
        if (self.dev)
          throw new VisibleError(
            "Cannot access `nodes.loadBalancer` in dev mode.",
          );
        if (!self.loadBalancer)
          throw new VisibleError(
            "Cannot access `nodes.loadBalancer` when no public ports are exposed.",
          );
        return self.loadBalancer;
      },

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Do not read `nodes.taskDefinition` when the app is in dev mode; gate the access with `$dev` (from `sst/dev`) so the code only runs on deploy.
  2. If you need the resource only for deployment-time wiring, move that logic behind `if (!$dev) { ... }` and provide a dev-mode alternative.
  3. Run `sst deploy` (not `sst dev`) for the workflow that requires the underlying Task Definition.

Example fix

// before
const td = service.nodes.taskDefinition;

// after
import { $dev } from "sst/dev";
const td = $dev ? undefined : service.nodes.taskDefinition;
Defensive patterns

Strategy: validation

Validate before calling

import { $dev } from "sst/dev";
if (!$dev) {
  const td = service.nodes.taskDefinition; // safe on deploy
}

Type guard

import { $dev } from "sst/dev";
const hasTaskDefinition = (): boolean => !$dev;

Try / catch

import { VisibleError } from "sst/platform/src/components/error"; // conceptual
try {
  const td = service.nodes.taskDefinition;
} catch (e) {
  if (String(e).includes("in dev mode")) {
    // dev-mode fallback: skip task-definition wiring
  } else throw e;
}

Prevention

When it happens

Trigger: Reading `service.nodes.taskDefinition` in an sst.config.ts while `sst dev` is running (i.e. `sst dev` with a Service component configured, or `dev.command` set so the component is in dev mode).

Common situations: Referencing `nodes.taskDefinition` to build an IAM policy, log group attachment, or custom ECS resource that unconditionally reads the property; the same sst.config.ts works on `sst deploy` but crashes under `sst dev` because dev mode is environment-dependent.

Related errors


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