benbjohnson/litestream · error

oss: delete all batch of %d objects: %w

Error message

oss: delete all batch of %d objects: %w

What it means

After listing all objects, DeleteAll deletes them in batches via DeleteMultipleObjects. A batch-level API failure is wrapped with the batch size. Like error 385 but scoped to the full-bucket delete path; per-object errors are surfaced by deleteResultError instead.

Source

Thrown at oss/replica_client.go:377

			if obj.Key != nil {
				objects = append(objects, oss.DeleteObject{Key: obj.Key})
			}
		}
	}

	// Delete all collected objects 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 all batch of %d objects: %w", n, err)
		} else if err := deleteResultError(batch, out); err != nil {
			return err
		}

		objects = objects[n:]
	}

	return nil
}

// ltxPath returns the full path to an LTX file.
func (c *ReplicaClient) ltxPath(level int, filename string) string {
	return c.Path + "/" + fmt.Sprintf("%04x/%s", level, filename)
}

// fileIterator represents an iterator over LTX files in OSS.
type fileIterator struct {
	ctx    context.Context

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Grant oss:DeleteObjects permission to the RAM role.
  2. If throttled (SlowDown in wrapped error), retry with backoff or delete during low-traffic periods.
  3. Confirm the bucket exists and the region/endpoint are correct.
  4. Re-run the operation; batch deletes are idempotent for already-deleted keys.

Example fix

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

Strategy: retry

Try / catch

if err := client.DeleteAll(ctx); err != nil {
    if strings.Contains(err.Error(), "SlowDown") { time.Sleep(time.Minute); return client.DeleteAll(ctx) }
    return err
}

Prevention

When it happens

Trigger: DeleteAll's deletion loop hitting AccessDenied, NoSuchBucket, throttling (SlowDown), or network failure when submitting a batch of n object keys.

Common situations: Deleting a very large number of LTX files and hitting OSS batch-delete rate limits; missing DeleteObjects permission; bucket state changed concurrently.

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/340ee5ac8a42d902. Report an issue: GitHub.