benbjohnson/litestream · error
abs: cannot list blobs: %w
Error message
abs: cannot list blobs: %w
What it means
This error is returned by ReplicaClient.DeleteAll when a page of the blob listing fails. DeleteAll pages through all blobs under the configured path prefix with a ListBlobsFlatPager and deletes each; if NextPage fails, listing (and thus the delete-all sweep) is aborted and the Azure error is wrapped with the key for diagnosis.
Source
Thrown at abs/replica_client.go:338
}
// List all blobs with the configured path prefix
prefix := "/"
if c.Path != "" {
prefix = strings.TrimSuffix(c.Path, "/") + "/"
}
pager := c.client.NewListBlobsFlatPager(c.Bucket, &azblob.ListBlobsFlatOptions{
Prefix: &prefix,
Include: azblob.ListBlobsInclude{Metadata: true},
})
for pager.More() {
internal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, "LIST").Inc()
resp, err := pager.NextPage(ctx)
if err != nil {
return fmt.Errorf("abs: cannot list blobs: %w", err)
}
for _, item := range resp.Segment.BlobItems {
internal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, "DELETE").Inc()
_, err := c.client.DeleteBlob(ctx, c.Bucket, *item.Name, nil)
if isNotExists(err) {
continue
} else if err != nil {
return fmt.Errorf("abs: cannot delete blob %q: %w", *item.Name, err)
}
}
}
return nil
}
type ltxFileIterator struct {View on GitHub (pinned to 4ed7a308f6)
Solutions
- Verify the container exists and the credentials have list permission on the account/container
- Check network connectivity and Azure status; retries are safe because DeleteAll is idempotent (missing blobs are skipped)
- Confirm the connection string / SAS token has not expired and the storage account endpoint is correct
- Re-run after fixing; there is no partial-state cleanup needed beyond re-invoking DeleteAll
Example fix
// before
err := client.DeleteAll(ctx) // fails listing with expired SAS
// after
if err := client.DeleteAll(ctx); err != nil {
var respErr *azcore.ResponseError
if errors.As(err, &respErr) && respErr.StatusCode == 403 {
// refresh SAS token / connection string, then retry
}
return err
} Defensive patterns
Strategy: retry
Validate before calling
// Go
if err := client.Init(ctx); err != nil { return err }
if _, err := client.client.NewListBlobsFlatPager(client.Bucket, &azblob.ListBlobsFlatOptions{Prefix: ptr("/")}).NextPage(ctx); err != nil {
return fmt.Errorf("list permission check failed: %w", err)
} Type guard
// Go
func isTransientListError(err error) bool {
var re *azcore.ResponseError
if errors.As(err, &re) {
return re.StatusCode >= 500 || re.StatusCode == 429 || re.StatusCode == 408
}
return errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.EOF)
} Try / catch
err := client.DeleteAll(ctx)
if err != nil && isTransientListError(err) {
err = retryWithBackoff(func() error { return client.DeleteAll(ctx) })
}
return err Prevention
- Verify list permission (SAS 'l' or Storage Blob Data Reader+) before wiping replicas
- Check container/account existence and endpoint config before running DeleteAll
- Use generous context timeouts for large containers — pagination can take minutes
- DeleteAll is idempotent; safe to re-run after any failure
When it happens
Trigger: Calling DeleteAll(ctx) while pager.NextPage(ctx) fails: invalid or expired credentials/SAS without list permission, storage account/container unreachable, firewall/DNS issues, or context cancellation mid-pagination.
Common situations: Wiping a replica with an account that can list but not enumerate (missing 'l' SAS permission); container deleted or renamed between listing pages; transient Azure outages; network blips during long delete sweeps.
Related errors
- abs: cannot delete ltx file %q: %w
- abs: cannot delete blob %q: %w
- close iterator: %w
- fetch ltx files: %w
- remove ltx files: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/f2b532b25bd380b2.
Report an issue: GitHub.