{"record":{"id":"f2b532b25bd380b2","repo":"benbjohnson/litestream","slug":"abs-cannot-list-blobs-w","errorCode":null,"errorMessage":"abs: cannot list blobs: %w","messagePattern":"abs: cannot list blobs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"abs/replica_client.go","lineNumber":338,"sourceCode":"\t}\n\n\t// List all blobs with the configured path prefix\n\tprefix := \"/\"\n\tif c.Path != \"\" {\n\t\tprefix = strings.TrimSuffix(c.Path, \"/\") + \"/\"\n\t}\n\n\tpager := c.client.NewListBlobsFlatPager(c.Bucket, &azblob.ListBlobsFlatOptions{\n\t\tPrefix:  &prefix,\n\t\tInclude: azblob.ListBlobsInclude{Metadata: true},\n\t})\n\n\tfor pager.More() {\n\t\tinternal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, \"LIST\").Inc()\n\n\t\tresp, err := pager.NextPage(ctx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"abs: cannot list blobs: %w\", err)\n\t\t}\n\n\t\tfor _, item := range resp.Segment.BlobItems {\n\t\t\tinternal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, \"DELETE\").Inc()\n\n\t\t\t_, err := c.client.DeleteBlob(ctx, c.Bucket, *item.Name, nil)\n\t\t\tif isNotExists(err) {\n\t\t\t\tcontinue\n\t\t\t} else if err != nil {\n\t\t\t\treturn fmt.Errorf(\"abs: cannot delete blob %q: %w\", *item.Name, err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\ntype ltxFileIterator struct {","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/abs/replica_client.go#L320-L356","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nerr := client.DeleteAll(ctx) // fails listing with expired SAS\n// after\nif err := client.DeleteAll(ctx); err != nil {\n\tvar respErr *azcore.ResponseError\n\tif errors.As(err, &respErr) && respErr.StatusCode == 403 {\n\t\t// refresh SAS token / connection string, then retry\n\t}\n\treturn err\n}","handlingStrategy":"retry","validationCode":"// Go\nif err := client.Init(ctx); err != nil { return err }\nif _, err := client.client.NewListBlobsFlatPager(client.Bucket, &azblob.ListBlobsFlatOptions{Prefix: ptr(\"/\")}).NextPage(ctx); err != nil {\n\treturn fmt.Errorf(\"list permission check failed: %w\", err)\n}","typeGuard":"// Go\nfunc isTransientListError(err error) bool {\n\tvar re *azcore.ResponseError\n\tif errors.As(err, &re) {\n\t\treturn re.StatusCode >= 500 || re.StatusCode == 429 || re.StatusCode == 408\n\t}\n\treturn errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.EOF)\n}","tryCatchPattern":"err := client.DeleteAll(ctx)\nif err != nil && isTransientListError(err) {\n\terr = retryWithBackoff(func() error { return client.DeleteAll(ctx) })\n}\nreturn err","preventionTips":["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"],"tags":["azure","storage","list","network","permissions"],"backgroundTag":"blob-list-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}