GoogleContainerTools/skaffold · error
bucket name is empty
Error message
bucket name is empty
What it means
parseGCSURI parses a gs:// URI into bucket and object components. After url.Parse, it requires the scheme to be 'gs' and the URI host component (the bucket) to be non-empty; an empty host means no bucket name was supplied, so it throws 'bucket name is empty'.
Source
Thrown at pkg/skaffold/gcs/client/native.go:142
if err != nil {
return err
}
}
return bucket.UploadObject(ctx, dstObj, f)
}
func (n *Native) parseGCSURI(uri string) (uriInfo, error) {
var gcsobj uriInfo
u, err := url.Parse(uri)
if err != nil {
return uriInfo{}, fmt.Errorf("cannot parse URI %q: %w", uri, err)
}
if u.Scheme != "gs" {
return uriInfo{}, fmt.Errorf("URI scheme is %q, must be 'gs'", u.Scheme)
}
if u.Host == "" {
return uriInfo{}, errors.New("bucket name is empty")
}
gcsobj.Bucket = u.Host
// If we do this with the url package it will scape the `?` character, breaking the glob.
gcsobj.ObjPath = strings.TrimLeft(strings.ReplaceAll(uri, "gs://"+u.Host, ""), "/")
return gcsobj, nil
}
func (n *Native) filesToDownload(ctx context.Context, bucket bucketHandler, urinfo uriInfo) (map[string]string, error) {
uriToLocalPath := map[string]string{}
// The exact match is with the original glob expression. This could be:
// 1. a/b/c -> It will return the file `c` under a/b/ if it exists
// 2. a/b/c* -> It will return any file under a/b/ that starts with c, e.g, c1, c-other, etc
// 3. a/b/c** -> It will return any file that starts with 'c', and files inside any folder starting with 'c'. It is doing the recursion already
exactMatches, err := bucket.ListObjects(ctx, &storage.Query{MatchGlob: urinfo.ObjPath})
if err != nil {
return nil, errView on GitHub (pinned to a1189de023)
Solutions
- Check the configured GCS URI and add the bucket name: 'gs://my-bucket/path'
- Verify the env/config variable holding the bucket name is non-empty before building the URI
- If using a path-style value like 'gs://bucket/obj', confirm no leading slash swallowed the bucket ('gs:///obj' is invalid)
Example fix
// before
uri := fmt.Sprintf("gs://%s/%s", os.Getenv("BUCKET"), object) // BUCKET empty -> gs:///obj
// after
bucket := os.Getenv("BUCKET")
if bucket == "" { log.Fatal("BUCKET env var must be set") }
uri := fmt.Sprintf("gs://%s/%s", bucket, object) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(cfg.GCSURI)
if err != nil || u.Scheme != "gs" || u.Host == "" {
return fmt.Errorf("GCS URI %q must include a bucket, e.g. gs://bucket/path", cfg.GCSURI)
} Type guard
func hasGCSBucket(uri string) bool {
u, err := url.Parse(uri)
return err == nil && u.Scheme == "gs" && u.Host != ""
} Prevention
- Never concatenate bucket names from possibly-empty env vars without a check
- Validate gs:// URIs at config load time with a regex like ^gs://[^/]+/.*$
- Prefer named config fields (bucket, object) over raw URI strings where possible
When it happens
Trigger: Calling DownloadRecursive or UploadFile with a URI like 'gs://' or 'gs:///path/only' where the authority/bucket part is missing; also with 'gs:///bucket-looks-like-path' forms.
Common situations: Config value for a GCS source or cache left as 'gs://' with no bucket; environment variable for bucket name empty so the URI concatenates to 'gs://' + '' + '/obj'; typo dropping the bucket from the path.
Related errors
- cannot parse URI %q: %w
- URI scheme is %q, must be 'gs'
- failed determining remote cache directory: %w
- failed determining Google Cloud Storage remote cache directo
- CONFIG_REMOTE_REPO_CACHE_NOT_FOUND_ERR
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/6e58fbccad9a6371.
Report an issue: GitHub.