benbjohnson/litestream · error

oss: delete batch of %d objects: %w

Error message

oss: delete batch of %d objects: %w

What it means

DeleteAll-style cleanup lists and then deletes objects in batches; DeleteMultipleObjects failed at the transport/API level for a batch of n objects. The error includes the batch size for debugging. Per-object deletion errors are handled separately via deleteResultError.

Source

Thrown at oss/replica_client.go:322

		key := c.ltxPath(info.Level, filename)
		objects = append(objects, oss.DeleteObject{Key: oss.Ptr(key)})

		c.logger.Debug("deleting ltx file", "level", info.Level, "minTXID", info.MinTXID, "maxTXID", info.MaxTXID, "key", key)
	}

	// Delete in batches
	for len(objects) > 0 {
		n := min(len(objects), MaxKeys)
		batch := objects[:n]

		request := &oss.DeleteMultipleObjectsRequest{
			Bucket:  oss.Ptr(c.Bucket),
			Objects: batch,
		}

		out, err := c.client.DeleteMultipleObjects(ctx, request)
		if err != nil {
			return fmt.Errorf("oss: delete batch of %d objects: %w", n, err)
		} else if err := deleteResultError(batch, out); err != nil {
			return err
		}

		internal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, "DELETE").Inc()

		objects = objects[n:]
	}

	return nil
}

// DeleteAll deletes all files.
func (c *ReplicaClient) DeleteAll(ctx context.Context) error {
	if err := c.Init(ctx); err != nil {
		return err
	}

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Grant the RAM role oss:DeleteObjects (and oss:DeleteObject) permission on the bucket/path.
  2. Check the wrapped OSS error code: throttling (SlowDown) means reduce retention churn or retry later.
  3. Verify the bucket still exists and the endpoint/region are correct.
  4. If a retention lock (compliance mode) blocks deletion, remove the lock or exclude this bucket from retention.

Example fix

// before (RAM policy)
{"Effect":"Allow","Action":["oss:PutObject","oss:GetObject"],"Resource":"acs:oss:*:*:my-bucket/*"}
// after
{"Effect":"Allow","Action":["oss:PutObject","oss:GetObject","oss:DeleteObject","oss:DeleteObjects"],"Resource":"acs:oss:*:*:my-bucket/*"}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check permission surface with a dry-run listing before enabling retention cleanup.
if _, err := client.ListLTXFiles(ctx); err != nil { return err }

Try / catch

err := client.DeleteLTXFiles(ctx, keys)
if err != nil {
    if strings.Contains(err.Error(), "SlowDown") { time.Sleep(backoff); return retry() }
    return fmt.Errorf("delete ltx: %w", err)
}

Prevention

When it happens

Trigger: Retenion/compaction cleanup calling DeleteLTXFiles when OSS returns an API-level error: AccessDenied on oss:DeleteObjects, NoSuchBucket, rate limiting, or network interruption.

Common situations: RAM policy grants Put/Get but not DeleteObjects; bucket under WORM/retention lock preventing deletes; throttling during mass retention cleanup of many LTX files.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/34b41445b13f388f. Report an issue: GitHub.