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
- Find the undefined element: log or inspect the `link` array passed to the failing component.
- Fix the conditional so the resource is always created, or use `.filter(Boolean)` to drop undefined entries before passing.
- If the resource should be optional, build the array conditionally: `link: [...(secret ? [secret] : [])]`.
- 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
- Use `.filter(Boolean)` on arrays built from conditional resources
- Type link arrays as `sst.Link.Linkable[]` so undefined elements fail typecheck
- Avoid `cond && resource` patterns in link arrays without filtering
- Enable strict TypeScript to catch undefined references at compile time
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
- Invalid function definition for the "${name}" Function
- Cannot access `nodes.loadBalancer` when no public ports are
- You must provide the ports to expose via "loadBalancer.rules
- You must provide a container name in "loadBalancer.rules" wh
- Invalid rule conditions for listen protocol "${v.listen}". O
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/f5a6eabeef09660d.
Report an issue: GitHub.