{"record":{"id":"871e27720fed094b","repo":"GoogleContainerTools/skaffold","slug":"failed-to-download-manifests-fom-gcs-w","errorCode":null,"errorMessage":"failed to download manifests fom GCS: %w","messagePattern":"failed to download manifests fom GCS: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/kubernetes/manifest/gcs.go","lineNumber":53,"sourceCode":"\nvar GetGCSClient = func() GCSClient {\n\treturn &client.Native{}\n}\n\n// DownloadFromGCS downloads all provided manifests from a remote GCS bucket,\n// and returns a relative path pointing to the GCS temp dir.\nfunc DownloadFromGCS(manifests []string) (string, error) {\n\tdir := filepath.Join(ManifestTmpDir, ManifestsFromGCS)\n\tif err := os.MkdirAll(dir, os.ModePerm); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create the tmp directory: %w\", err)\n\t}\n\tfor _, manifest := range manifests {\n\t\tif manifest == \"\" || !strings.HasPrefix(manifest, gcsPrefix) {\n\t\t\treturn \"\", fmt.Errorf(\"%v is not a valid GCS path\", manifest)\n\t\t}\n\t\tgcs := GetGCSClient()\n\t\tif err := gcs.DownloadRecursive(context.Background(), manifest, dir); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to download manifests fom GCS: %w\", err)\n\t\t}\n\t}\n\treturn ManifestTmpDir, nil\n}\n","sourceCodeStart":35,"sourceCodeEnd":58,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/kubernetes/manifest/gcs.go#L35-L58","documentation":"For each valid gs:// path, DownloadFromGCS calls the GCS client's DownloadRecursive; any download failure (bucket missing, object missing, auth error, network error) is wrapped as 'failed to download manifests fom GCS' (note the upstream typo).","triggerScenarios":"Calling manifest.DownloadFromGCS when gcs.DownloadRecursive fails: nonexistent bucket/object, 401/403 from missing or expired credentials (GOOGLE_APPLICATION_CREDENTIALS), or network/DNS failure contacting storage.googleapis.com.","commonSituations":"Private buckets without application-default credentials ('gcloud auth application-default login'), wrong bucket name/region, CI runners without the storage.objects.get permission on the service account, or air-gapped environments without GCS reachability.","solutions":["Verify the gs:// bucket and object path exist with 'gsutil ls gs://bucket/path'","Set up credentials: 'gcloud auth application-default login' locally, or attach a service account with Storage Object Viewer in CI","Check the wrapped cause (%w) to distinguish 403 auth vs 404 not-found vs network errors","Retry on transient network errors; fix VPC/DNS/firewall if storage.googleapis.com is unreachable"],"exampleFix":"// before: no credentials in CI\ngs://my-private-bucket/manifests  -> 403\n// after: provide credentials\necho \"$GCP_SA_KEY\" > /tmp/sa.json\nexport GOOGLE_APPLICATION_CREDENTIALS=/tmp/sa.json","handlingStrategy":"retry","validationCode":"import \"os/exec\"\nfunc gcsPathExists(gsURI string) bool {\n  return exec.Command(\"gsutil\", \"ls\", gsURI).Run() == nil\n}\n// also verify credentials: os.Getenv(\"GOOGLE_APPLICATION_CREDENTIALS\") or ADC present","typeGuard":null,"tryCatchPattern":"path, err := manifest.DownloadFromGCS(manifests)\nif err != nil && strings.Contains(err.Error(), \"failed to download manifests fom GCS\") {\n  // transient network errors: retry with backoff; auth/notfound: surface cause\n  for i := 0; i < 3; i++ {\n    time.Sleep(time.Duration(1<<i) * time.Second)\n    if path, err = manifest.DownloadFromGCS(manifests); err == nil { break }\n  }\n}","preventionTips":["Set up ADC locally ('gcloud auth application-default login') and workload identity/service-account keys in CI","Grant the running identity storage.objects.get/list on the bucket","Verify bucket paths with 'gsutil ls' before automating downloads","Add retry with backoff for transient network failures; check egress/DNS in restricted environments"],"tags":["gcs","network","auth","download"],"backgroundTag":"gcs-download-failed","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}