# S3 Incomplete Multipart Uploads Accumulating

> Incomplete multipart uploads left in S3 buckets without an abort lifecycle rule keep billing invisible part storage. ZopNight requires a measured incomplete_multipart_count above 0 as evidence, but abstains on every bucket today: the wasted-bytes figure needs paid Storage Lens Advanced metrics or an O(uploads×parts) scan, so no cheap producer exists.

Source: https://zop.dev/integrations/aws/recommendations/s3-incomplete-multipart-uploads-accumulating
Updated: 2026-08-19

---

## Measured abandoned uploads, not a missing rule

- Metadata["multipart_abort_rule_present"] (JSON bool) must be false; the prior abort_incomplete_multipart tag-absence-as-proof gate is replaced; abstains when the key is absent (lifecycle config unreadable).
- Metadata["incomplete_multipart_count"] > 0 (evidence gate, audit 2026-06-26: config-absence alone is not evidence of waste; an explicit 0 means "measured, none found").
- PricingAware: per-resource monthly cost, used only as the pricing-available applicability gate and never as the saving (using the whole-bucket cost overstated ~100×, the EV-T0043 bug).
- SKURatesAware: standardstorage per-GiB-HOUR rate (PRODUCER-GAP: not yet ingested → LookupSKURate returns 0 → abstain).
- PRODUCER-GAP (PERMANENT v1-abstain) incomplete_multipart_bytes: has no cheap per-bucket producer and is intentionally not wired; the only sources are per-upload S3 ListParts (the O(uploads×parts) fan-out the discoverer deliberately avoids) or the Storage-Lens ADVANCED IncompleteMultipartUploadStorageBytes metric (paid, opt-in, off by default). metadataFloatS3Multipart returns ok=false, so the rule always abstains on the saving dimension.

## Why the wasted bytes cannot be measured cheaply

concrete-or-abstain (cost-driven "orphan"). The intended saving is wastedGiB × [the StandardStorage per-GiB-HOUR rate](https://aws.amazon.com/s3/pricing/) × 730 (the per-GiB-HOUR rate ×730 → monthly, mirroring GCP RC-147; CurrentCostUSD=SavingsUSD, OptimizedCostUSD=0). The prior code emitted SavingsUSD=0/100%-of-bucket-cost fabrications; now the rule emits a rec only when both the wasted-bytes producer signal and the StandardStorage rate are present. Because incomplete_multipart_bytes is a PERMANENT v1-abstain (no cheap per-bucket producer) and standardstorage is not yet ingested, the rule currently abstains (returns nil) on every bucket and never emits a $0/fabricated cost rec.

## Adding a 7-day abort rule

1. Go to S3 Console → Select bucket → Management
2. Create lifecycle rule
3. Check 'Clean up expired object delete markers'
4. Check 'Clean up incomplete multipart uploads' after 7 days

## No metrics, just the standard storage rate

None (SKURatesAware: standardstorage per-GiB-HOUR rate)
