GoogleContainerTools/skaffold · error
failed to cache Google Cloud Storage objects from %q: %w
Error message
failed to cache Google Cloud Storage objects from %q: %w
What it means
After the per-source cache directory is prepared, SyncObjects downloads all objects from the configured GCS source into it via gcs.DownloadRecursive (the native GCS client). If that download fails, the client's error is wrapped with this message. It means the remote GCS objects could not be fetched and cached locally, so the build/deploy depending on them cannot proceed.
Source
Thrown at pkg/skaffold/gcs/gsutil.go:115
}
// The subdirectory needs to exist to work with gsutil.
if err := os.MkdirAll(cacheDir, 0700); err != nil {
return "", fmt.Errorf("failed creating Google Cloud Storage cache directory for %q: %w", g.Source, err)
}
} else {
// If sync property is false then skip fetching latest object from remote storage.
if g.Sync != nil && !*g.Sync {
return cacheDir, nil
}
// If sync is turned off via flag `--sync-remote-cache` then skip fetching latest object from remote storage.
if opts.SyncRemoteCache.FetchDisabled() {
return cacheDir, nil
}
}
gcs := GetGCSClient()
if err := gcs.DownloadRecursive(ctx, g.Source, cacheDir); err != nil {
return "", fmt.Errorf("failed to cache Google Cloud Storage objects from %q: %w", g.Source, err)
}
return cacheDir, nil
}
// getPerSourceDir returns the directory used per Google Cloud Storage source. Directory is a hash of the source provided.
func getPerSourceDir(g latest.GoogleCloudStorageInfo) (string, error) {
inputs := []string{g.Source}
hasher := sha256.New()
enc := json.NewEncoder(hasher)
if err := enc.Encode(inputs); err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(hasher.Sum(nil))[:32], nil
}
// syncDisabledErr returns error to use when remote sync is turned off by the user and the Google Cloud Storage object doesn't exist inside the cache directory.
func syncDisabledErr(g latest.GoogleCloudStorageInfo, cacheDir string) error {View on GitHub (pinned to a1189de023)
Solutions
- Verify the gs:// source URI in your skaffold config is correct and the bucket/prefix still exists (gsutil ls gs://<bucket>).
- Authenticate with GCP: gcloud auth application-default login locally, or configure a service account/Workload Identity in CI, and confirm the account has storage.objects.get/list on the bucket.
- Run a manual download (gcloud storage cp -r gs://<source> <dir>) to reproduce and see the raw client error.
- Check network/proxy access to storage.googleapis.com and retry; populate the cache manually if sync is disabled.
Example fix
// before sync: source: gs://my-bucket/manifests # bucket deleted // after gcloud storage ls gs://my-bucket/ # verify bucket exists first sync: source: gs://my-correct-bucket/manifests
Defensive patterns
Strategy: try-catch
Validate before calling
// before invoking skaffold, verify source and access gcloud storage ls gs://my-bucket/manifests >/dev/null 2>&1 || \ echo "GCS source missing or no access; check URI and credentials" gcloud auth application-default print-access-token >/dev/null 2>&1 || \ echo "No valid GCP credentials"
Type guard
func isGCSErrNotFound(err error) bool {
var gerr *googleapi.Error
return errors.As(err, &gerr) && gerr.Code == 404
} Try / catch
cacheDir, err := gcs.SyncObjects(ctx, gcsInfo, opts)
if err != nil {
if strings.Contains(err.Error(), "failed to cache Google Cloud Storage objects") {
log.Warnf("GCS fetch failed; verify `gcloud storage ls %s` and credentials: %v", gcsInfo.Source, err)
return useManuallyPopulatedCache() // fallback path
}
return err
} Prevention
- Lint skaffold configs so gs:// sources are validated (bucket exists, prefix non-empty) before runs.
- Authenticate in CI with Workload Identity or a service-account key that has storage.objects.get/list on the bucket.
- Pre-populate the cache and set sync: false for immutable artifacts to avoid repeated network fetches.
- Set sync-remote-cache=missing to tolerate offline runs when the cache is already warm.
When it happens
Trigger: Calling SyncObjects/cacheGCSObject where gcs.DownloadRecursive(ctx, g.Source, cacheDir) fails: source URI is wrong/empty, bucket doesn't exist, no authenticated GCP credentials, no access to the bucket, or network unavailable.
Common situations: Typo in the gs:// source URI in the skaffold config; gcloud/application-default credentials missing or expired (CI without Workload Identity/service-account key); insufficient IAM on the bucket; corporate proxy blocking storage.googleapis.com; deleted bucket.
Related errors
- downloading from GCS: %w
- CONFIG_REMOTE_REPO_CACHE_NOT_FOUND_ERR
- error creating GCS Client: %w
- failed to iterate objects: %v
- failed to read object: %v
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/5e1779bd428eda7b.
Report an issue: GitHub.