{"record":{"id":"627a33672e0a1f64","repo":"GoogleContainerTools/skaffold","slug":"downloading-from-gcs-w","errorCode":null,"errorMessage":"downloading from GCS: %w","messagePattern":"downloading from GCS: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/render/generate/generate.go","lineNumber":99,"sourceCode":"\t\t\tgcsManifests = append(gcsManifests, path)\n\t\tdefault:\n\t\t\t// expand paths\n\t\t\tpath, err := util.ExpandEnvTemplate(path, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlocalPaths = append(localPaths, path)\n\t\t}\n\t}\n\tlist, err := util.ExpandPathsGlob(workdir, localPaths)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(gcsManifests) != 0 {\n\t\t// return tmp dir of the downloaded manifests\n\t\ttmpDir, err := manifest.DownloadFromGCS(gcsManifests)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"downloading from GCS: %w\", err)\n\t\t}\n\t\tl, err := util.ExpandPathsGlob(tmpDir, []string{\"*\"})\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"expanding kubectl manifest paths: %w\", err)\n\t\t}\n\t\tlist = append(list, l...)\n\t}\n\tif len(urlManifests) != 0 {\n\t\tpaths, err := manifest.DownloadFromURL(urlManifests)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlist = append(list, paths...)\n\t}\n\treturn list, nil\n}\n\n// Generate parses the config resources from the paths in .Generate.Manifests. This path can be the path to raw manifest,","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/render/generate/generate.go#L81-L117","documentation":"Skaffold's render generator wraps any failure from manifest.DownloadFromGCS with this message. DownloadFromGCS fetches Kubernetes manifests stored in Google Cloud Storage buckets into a temporary directory so they can be rendered locally. The wrap means a GCS download (auth, network, object-not-found) failed while resolving the rawK8s manifest list in resolveRemoteAndLocal.","triggerScenarios":"A skaffold.yaml render.generate.rawK8s entry with a gs:// URL, causing resolveRemoteAndLocal to call manifest.DownloadFromGCS, which returns an error (network failure, missing object, insufficient GCS permissions).","commonSituations":"gs:// object path typo or deleted bucket; no gcloud credentials / Application Default Credentials available (CI without auth); firewall blocking storage.googleapis.com; service account lacking storage.objects.get.","solutions":["Verify the gs:// paths in rawK8s exist: gsutil ls gs://<bucket>/<path>","Authenticate: run gcloud auth application-default login (or configure the CI service account with Storage Object Viewer)","Test network access to storage.googleapis.com (proxy/firewall may block it)","As a fallback, download the manifests manually and reference local paths in rawK8s"],"exampleFix":"// before: unauthenticated CI can't reach GCS\nrawK8s:\n  - gs://my-bucket/manifests/*.yaml\n// after: pre-fetch with auth or use local paths\nrawK8s:\n  - ./manifests/*.yaml","handlingStrategy":"try-catch","validationCode":"gsutil ls gs://my-bucket/manifests/ >/dev/null 2>&1 || echo 'GCS path missing or unauthorized'","typeGuard":null,"tryCatchPattern":"manifests, err := gen.Generate(ctx, out)\nif err != nil && strings.Contains(err.Error(), \"downloading from GCS\") {\n    // check gcloud auth: gcloud auth application-default login\n    // verify gs:// paths and network, then retry\n}","preventionTips":["Verify gs:// paths with gsutil ls before adding them to rawK8s","Ensure CI has Application Default Credentials or a service account with Storage Object Viewer","Keep kustomize-style remote references on stable, non-deleted buckets"],"tags":["gcs","network","manifest-download","authentication"],"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"}