GoogleContainerTools/skaffold · error
failed to iterate objects: %v
Error message
failed to iterate objects: %v
What it means
ListObjects wraps errors from the storage object iterator while listing bucket objects matching a query (MatchGlob or Prefix). It means listing failed mid-iteration — typically an API-level failure such as the bucket not existing, permission denied, or a transient server/network error. No object names are returned in that case.
Source
Thrown at pkg/skaffold/gcs/client/native.go:313
// nativeBucketHandler implements a handler using the Cloud client libraries.
type nativeBucketHandler struct {
storageClient *storage.Client
bucket *storage.BucketHandle
}
func (nb nativeBucketHandler) ListObjects(ctx context.Context, q *storage.Query) ([]string, error) {
matches := []string{}
it := nb.bucket.Objects(ctx, q)
for {
attrs, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return nil, fmt.Errorf("failed to iterate objects: %v", err)
}
if attrs.Name != "" {
matches = append(matches, attrs.Name)
}
}
return matches, nil
}
func (nb nativeBucketHandler) DownloadObject(ctx context.Context, localPath, uri string) error {
reader, err := nb.bucket.Object(uri).NewReader(ctx)
if err != nil {
return fmt.Errorf("failed to read object: %v", err)
}
defer reader.Close()
file, err := os.Create(localPath)
if err != nil {View on GitHub (pinned to a1189de023)
Solutions
- Check the wrapped error: if 'bucket doesn't exist', fix the bucket name in the gs:// URI
- Grant the service account roles/storage.objectViewer (or objectAdmin) on the bucket
- Retry transient errors (429/5xx); consider backoff for rate limits
- Verify network/proxy access to storage.googleapis.com from your environment
Example fix
// before
if err := n.DownloadRecursive(ctx, "gs://my-bukket/dir/**", dst); err != nil { log.Fatal(err) } // 404
// after
if err := gcloudBucketExists("my-bucket") { /* validate first */ }
if err := n.DownloadRecursive(ctx, "gs://my-bucket/dir/**", dst); err != nil { log.Fatal(err) } Defensive patterns
Strategy: retry
Validate before calling
func checkBucketReadable(ctx context.Context, bucketName string) error {
client, err := storage.NewClient(ctx)
if err != nil { return err }
defer client.Close()
_, err = client.Bucket(bucketName).Attrs(ctx)
return err // 404 => wrong name, 403 => missing permission
}
// call before DownloadRecursive with the parsed bucket name Try / catch
err := n.DownloadRecursive(ctx, src, dst)
if err != nil {
if strings.Contains(err.Error(), "failed to iterate objects") {
// transient? retry with backoff
err = retryBackoff(3, 2*time.Second, func() error {
return n.DownloadRecursive(ctx, src, dst)
})
}
return err
} Prevention
- Verify bucket name and existence before listing
- Grant storage.objectViewer to the identity used
- Add bounded retry with backoff for 429/5xx listing errors
- Check the MatchGlob pattern is valid GCS glob syntax
When it happens
Trigger: Native.DownloadRecursive listing with MatchGlob, or isGCSDirectory listing with Prefix, when the bucket does not exist, the caller lacks storage.objects.list permission, or the iterator hits a 4xx/5xx from the GCS API.
Common situations: Typo in the bucket name in gs:// URI (404 storage: bucket doesn't exist); service account missing roles/storage.objectViewer; transient 429/503 from GCS during heavy CI use; network interruption mid-listing.
Related errors
- failed to read object: %v
- DEPLOY_CLOUD_RUN_GET_SERVICE_ERR
- failed to create directory: %v
- failed to create file: %v
- failed to copy object to file: %v
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/bd752be8fb62fe75.
Report an issue: GitHub.