anomalyco/sst · error · VisibleError

An undefined link was passed into a `link` array.

Error message

An undefined link was passed into a `link` array.

What it means

`Link.build()` takes an array of resources passed to a component's `link` property and converts linkable ones into link definitions. Before filtering, it validates each array element; if any element is falsy (undefined/null), SST throws this VisibleError instead of silently dropping the broken entry, since it almost always indicates a mistake in the app config.

Source

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

        props: args.props,
      };
    });
  }

  export interface Linkable {
    urn: Output<string>;
    getSSTLink(): Definition;
  }

  export function isLinkable(obj: any): obj is Linkable {
    return "getSSTLink" in obj;
  }

  export function build(links: any[]) {
    return links
      .map((link) => {
        if (!link)
          throw new VisibleError(
            "An undefined link was passed into a `link` array.",
          );
        return link;
      })
      .filter((l) => isLinkable(l))
      .map((l: Linkable) => {
        const link = l.getSSTLink();
        return all([l.urn, link]).apply(([urn, link]) => ({
          name: urn.split("::").at(-1)!,
          properties: {
            ...link.properties,
            type: normalizeType(urn.split("::").at(-2)!),
          },
        }));
      });
  }

  export function getProperties(links?: Input<any[]>) {

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Find the undefined element: log or inspect the `link` array passed to the failing component.
  2. Fix the conditional so the resource is always created, or use `.filter(Boolean)` to drop undefined entries before passing.
  3. If the resource should be optional, build the array conditionally: `link: [...(secret ? [secret] : [])]`.
  4. Enable TypeScript strictness so an undefined reference is caught at compile time.

Example fix

// before
const secret = stage === "prod" ? new sst.Secret("MySecret") : undefined;
new sst.aws.Function("Api", { link: [secret] });
// after
const secret = stage === "prod" ? new sst.Secret("MySecret") : undefined;
new sst.aws.Function("Api", { link: [secret].filter(Boolean) });
Defensive patterns

Strategy: type-guard

Validate before calling

// Before passing a link array
function validLinks(links: unknown[]) {
  return links.filter((l): l is NonNullable<typeof l> => !!l);
}
new sst.aws.Function("Api", { link: validLinks([bucket, secret]) });

Type guard

function isLinkableResource(l: unknown): l is sst.Link.Linkable {
  return !!l && typeof l === "object" && "getSSTLink" in l;
}

Try / catch

try {
  const fn = new sst.aws.Function("Api", { link: links });
} catch (e) {
  if (String(e).includes("undefined link")) {
    console.error("A link entry is undefined — check conditional resource creation:", links);
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing an array containing undefined/null into a `link` option, e.g. `new sst.aws.Function("Api", { link: [bucket, missingSecret] })` where `missingSecret` is undefined — commonly from a conditional like `link: [stage === "prod" && secret].filter(Boolean)` without the filter, or referencing a resource created behind an if-branch.

Common situations: Conditionally created resources where the component variable stays undefined; typos in variable names resolved to undefined (no TS error if typed as any); destructuring an object with a missing key; a ternary that yields undefined instead of an empty array element.

Related errors


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