anomalyco/sst · error · VisibleError
Lifecycle rule at index ${index} has an empty or whitespace-
Error message
Lifecycle rule at index ${index} has an empty or whitespace-only "id". Please provide a valid id or omit it to use the auto-generated id. What it means
S3 lifecycle rule IDs must be non-empty, and SST additionally rejects whitespace-only IDs. When a lifecycle rule's `id` trims to an empty string, SST throws this VisibleError because S3 would reject it and auto-generated IDs are the intended default. Omitting `id` entirely lets SST generate `${name}LifecycleRule${index}`.
Source
Thrown at platform/src/components/aws/bucket.ts:971
},
{ parent },
),
);
});
}
function createLifecycle() {
return output(args.lifecycle).apply((lifecycleRules) => {
if (!lifecycleRules || lifecycleRules.length === 0) return;
const seenIds = new Map<string, number>();
const resolvedIds = lifecycleRules.map((rule, index) => {
const rawId = rule.id ?? `${name}LifecycleRule${index}`;
const resolvedId = rawId.trim();
if (resolvedId.length === 0) {
throw new VisibleError(
`Lifecycle rule at index ${index} has an empty or whitespace-only "id". Please provide a valid id or omit it to use the auto-generated id.`,
);
}
if (resolvedId.length > 255) {
throw new VisibleError(
`Lifecycle rule at index ${index} has an "id" that is ${resolvedId.length} characters long. AWS S3 lifecycle rule IDs cannot exceed 255 characters.`,
);
}
const existingIndex = seenIds.get(resolvedId);
if (existingIndex !== undefined) {
throw new VisibleError(
`Lifecycle rule "id" values must be unique. The id "${resolvedId}" is used by rules at indexes ${existingIndex} and ${index}.`,
);
}
seenIds.set(resolvedId, index);
View on GitHub (pinned to a0bd20f762)
Solutions
- Omit the `id` field so SST auto-generates a valid ID
- Provide a meaningful non-empty, non-whitespace id for the rule
- Validate/trim the id source (env var, config) upstream and fall back to omitting it when empty
Example fix
// before
transform: {
bucket: { lifecycleRules: [{ id: "", status: "Enabled", expiration: { days: 30 } }] }
}
// after
transform: {
bucket: { lifecycleRules: [{ status: "Enabled", expiration: { days: 30 } }] }
} Defensive patterns
Strategy: validation
Validate before calling
rules.forEach((r, i) => {
if (r.id != null && r.id.trim() === "") {
delete r.id; // fall back to auto-generated id
}
}); Type guard
function hasValidLifecycleId(r: { id?: string }): boolean {
return r.id === undefined || r.id.trim().length > 0;
} Try / catch
try {
new sst.aws.Bucket("B", { transform: { bucket: { lifecycleRules: rules } } });
} catch (e) {
if ((e as Error).message.includes("empty or whitespace-only")) {
console.error("Fix or drop the empty lifecycle rule id");
}
throw e;
} Prevention
- Omit `id` rather than passing an empty string; SST auto-generates one
- Trim and validate any id sourced from env vars or external config
- Keep lifecycle rule definitions in typed, reviewed config modules
When it happens
Trigger: Passing a lifecycle rule in `bucket.transform` or lifecycle args with `id: ""` or `id: " "` (whitespace only).
Common situations: Setting `id` from an env var or user config that is blank; building rule objects programmatically with an uninitialized id field; trimming user input without checking emptiness before assigning.
Related errors
- At least one of function, queue, or topic is required for th
- Only one of function, queue, or topic is allowed for the "${
- The DNS record "${partial.name}" cannot be created because t
- Unsupported storage: ${v}. The supported value for storage i
- type === "service" ? `You cannot provide both "containers" a
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/e62e13478f5bc2d4.
Report an issue: GitHub.