apache/beam · error

bucket must be non-empty

Error message

bucket must be non-empty

What it means

MakeObject builds a gs:// object path from a bucket and path and panics if the bucket string is empty, since a GCS path without a bucket is meaningless. It is a fail-fast guard for a programmer/config error rather than a runtime condition.

Solutions

  1. Ensure the bucket value is set and non-empty before calling MakeObject
  2. Check the flag/env variable supplying the bucket (e.g. --staging_location, GCS bucket option)
  3. Add an explicit empty-string check with a helpful message before constructing the path
  4. Parse a full gs:// path with ParseObject to derive the bucket instead of hardcoding ""

Example fix

// before
obj := gcsx.MakeObject(bucket, path) // panics when bucket == ""
// after
if bucket == "" {
	return fmt.Errorf("--staging_bucket must be set")
}
obj := gcsx.MakeObject(bucket, path)
Defensive patterns

Strategy: validation

Validate before calling

if bucket == "" {
	return fmt.Errorf("bucket must be provided (check --staging_location / GCS config)")
}

Type guard

func hasBucket(object string) bool { b, _ := gcsx.ParseObject(object); return b != "" }

Prevention

When it happens

Trigger: Calling gcsx.MakeObject("", "some/path"), or calling it via Join/CommitManifest/PutArtifact with a path derived from an empty bucket — e.g. an unset or empty --artifact/staging bucket flag.

Common situations: Missing command-line flag for staging/artifact bucket; empty GCS_BUCKET environment variable; a pipeline option defaulting to "" that is fed straight into MakeObject.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/258eb950dbbc13c4. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/util/gcsx/gcs.go:129

	}
	return w.Close()
}

// ReadObject reads the content of the given object in full.
func ReadObject(ctx context.Context, client *storage.Client, bucket, object string) ([]byte, error) {
	r, err := client.Bucket(bucket).Object(object).NewReader(ctx)
	if err != nil {
		return nil, err
	}
	return io.ReadAll(r)
}

// MakeObject creates a object location from bucket and path. For example,
// MakeObject("foo", "bar/baz") returns "gs://foo/bar/baz". The bucket
// must be non-empty.
func MakeObject(bucket, path string) string {
	if bucket == "" {
		panic("bucket must be non-empty")
	}
	return fmt.Sprintf("gs://%v/%v", bucket, path)
}

// ParseObject deconstructs a GCS object name into (bucket, name).
func ParseObject(object string) (bucket, path string, err error) {
	parsed, err := url.Parse(object)
	if err != nil {
		return "", "", err
	}

	if parsed.Scheme != "gs" {
		return "", "", errors.Errorf("object %s must have 'gs' scheme", object)
	}
	if parsed.Host == "" {
		return "", "", errors.Errorf("object %s must have bucket", object)
	}
	if parsed.Path == "" {

View on GitHub (pinned to 12126d8942)