anomalyco/sst · error
failed to delete state object %s version %s: %s
Error message
failed to delete state object %s version %s: %s
What it means
`deleteObjectVersions` batch-deletes S3 object versions (used by `pruneNoncurrentVersions` and `purge` when resetting stage state). AWS `DeleteObjects` returns per-object errors in the response body rather than via the Go error, so when `out.Errors` is non-empty SST surfaces the first one with the key, version ID, and AWS message.
Source
Thrown at pkg/project/provider/aws.go:789
return ids
}
func (a *AwsHome) deleteObjectVersions(s3Client *s3.Client, bucket string, ids []s3types.ObjectIdentifier) error {
for i := 0; i < len(ids); i += 1000 {
end := i + 1000
if end > len(ids) {
end = len(ids)
}
out, err := s3Client.DeleteObjects(context.TODO(), &s3.DeleteObjectsInput{
Bucket: aws.String(bucket),
Delete: &s3types.Delete{Objects: ids[i:end], Quiet: aws.Bool(true)},
})
if err != nil {
return err
}
if len(out.Errors) > 0 {
item := out.Errors[0]
return fmt.Errorf("failed to delete state object %s version %s: %s", aws.ToString(item.Key), aws.ToString(item.VersionId), aws.ToString(item.Message))
}
}
return nil
}
func (a *AwsHome) purge(app, stage string) error {
bootstrap, err := a.provider.Bootstrap(a.provider.config.Region)
if err != nil {
return err
}
s3Client := s3.NewFromConfig(a.provider.config)
prefixes := []string{
a.pathForData("app", app, stage),
a.pathForData("secret", app, stage),
path.Join("update", app, stage) + "/",
path.Join("summary", app, stage) + "/",
path.Join("eventlog", app, stage) + "/",View on GitHub (pinned to a0bd20f762)
Solutions
- Read the `%s` message suffix for the concrete AWS reason (AccessDenied, InvalidRequest, etc.) and fix accordingly
- Grant the credentials `s3:DeleteObjectVersion` on the state bucket and its contents
- If Object Lock/retention is set, wait out or remove the retention before purging
Defensive patterns
Strategy: retry
Validate before calling
aws iam simulate-principal-policy --policy-source-arn <deploy-role-arn> --action-names s3:DeleteObjectVersion s3:DeleteObject --resource-arns arn:aws:s3:::sst-state-bucket/*
Try / catch
err := sstPurge(ctx, app, stage)
if err != nil && strings.Contains(err.Error(), "failed to delete state object") {
if strings.Contains(err.Error(), "AccessDenied") {
// fix IAM, then retry once
err = sstPurge(ctx, app, stage)
}
} Prevention
- Grant s3:DeleteObjectVersion in addition to s3:DeleteObject for the state bucket
- Don't enable Object Lock/retention on SST state buckets
- Check the AWS message suffix in the error for the exact cause before retrying
When it happens
Trigger: Purging a stage (`sst purge`/unlock flow) or pruning noncurrent versions when at least one object version cannot be deleted — e.g. `AccessDenied`, version-controlled object protected by policy, or retention/legal hold.
Common situations: Bucket policies denying `s3:DeleteObjectVersion`; S3 Object Lock retention on state files; IAM missing `s3:DeleteObjectVersion` while having `s3:DeleteObject`.
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 "${
- Lifecycle rule at index ${index} has an empty or whitespace-
- failed to delete S3 bucket %s: %w
- failed to marshal policy for bucket %s: %w
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/de1dd39cc9242baf.
Report an issue: GitHub.