anomalyco/sst · error · VisibleError

Component name "${args.name}" is reserved. Please choose a d

Error message

Component name "${args.name}" is reserved. Please choose a different name for your "${args.type}" component.

What it means

SST reserves the component name "app" (case-insensitive) for top-level SST components, because the name is used internally (e.g. for app/linking infrastructure) and would collide. During stack registration, `Link.reset()` installs a stack transformation that rejects any top-level linkable SST component whose lowercase name equals "app" by throwing a VisibleError.

Source

Thrown at platform/src/components/link.ts:61

          ...properties,
        },
      });
    }
  }

  export function reset() {
    const links = new Set<string>();
    // Ensure component names are unique
    runtime.registerStackTransformation((args) => {
      const isLinkable =
        args.type.startsWith("sst:") ||
        Linkable.wrappedResources.has(args.type);
      if (isLinkable && !args.opts.parent) {
        const lcname = args.name.toLowerCase();

        // "App" is reserved and cannot be used as a component name.
        if (lcname === "app") {
          throw new VisibleError(
            `Component name "${args.name}" is reserved. Please choose a different name for your "${args.type}" component.`,
          );
        }

        // Ensure linkable resources have unique names. This includes all SST components
        // and non-SST components that are linkable.
        if (links.has(lcname)) {
          throw new VisibleError(`Component name ${args.name} is not unique.`);
        }
        links.add(lcname);
      }
      return {
        opts: args.opts,
        props: args.props,
      };
    });

    // Create link refs

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Rename the component to something other than "App"/"app" in sst.config.ts, e.g. "MyApp" or "Api".
  2. Check casing: the check is case-insensitive, so "APP", "app", and "App" all fail.
  3. If the component is not intentionally top-level, give it a parent so the transformation skips it.
  4. Run `sst deploy`/`sst dev` again after renaming; also update references to the component's resource name in links or Resource lookups.

Example fix

// before
const app = new sst.aws.Function("App", {
  handler: "src/api.handler",
});
// after
const app = new sst.aws.Function("Api", {
  handler: "src/api.handler",
});
Defensive patterns

Strategy: validation

Validate before calling

// In sst.config.ts, before creating a top-level component
function assertValidComponentName(name: string) {
  if (name.toLowerCase() === "app")
    throw new Error(`Component name "${name}" is reserved; use a different name.`);
  return name;
}
const name = assertValidComponentName("Api");

Type guard

function isReservedName(name: string): boolean {
  return name.toLowerCase() === "app";
}

Prevention

When it happens

Trigger: Declaring any top-level SST component (one without a parent) named "App" or "app" in any casing, e.g. `new sst.aws.Function("App", {...})` or a wrapped linkable resource named "app" in sst.config.ts. Only fires when the resource type starts with `sst:` or is in Linkable.wrappedResources and has no parent.

Common situations: Copying example code that names the primary function/app component "App"; renaming a component to match a variable called `app`; typos where the developer intended `new sst.App(...)`-style naming; refactors where a subcomponent lost its parent and became top-level.

Related errors


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