apache/beam · error

project cannot be empty, got

Error message

project cannot be empty, got %v

What it means

RequesterBillingProject configures the project billed for GCS requester-pays operations, and it rejects an empty project string. Since an empty billing project can never be valid for GCS API calls, the function fails fast with this error instead of deferring to a confusing GCS-side auth error.

Solutions

  1. Pass a valid non-empty GCP project ID.
  2. Guard before calling: check the value is non-empty and fail earlier with a clearer message.
  3. Fix the source (flag, env var, config key) that produced the empty string.
  4. Wire a sensible default project for the environment.

Example fix

// before
if err := gcs.RequesterBillingProject(project); err != nil { ... } // project == ""
// after
if project == "" {
	return fmt.Errorf("billing project must be set via --gcs_billing_project")
}
if err := gcs.RequesterBillingProject(project); err != nil { ... }
Defensive patterns

Strategy: validation

Validate before calling

if project == "" {
	return errors.New("GCS billing project must be a non-empty GCP project ID")
}
return gcs.RequesterBillingProject(project)

Try / catch

if err := gcs.RequesterBillingProject(project); err != nil {
	if strings.Contains(err.Error(), "project cannot be empty") {
		return fmt.Errorf("set --gcs_billing_project: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling RequesterBillingProject("") — typically from an empty config value, unset flag, or an environment variable/env lookup that returned "".

Common situations: Flag/env not set in CI; config file key missing so the default empty string is passed; test code forgot to set the project.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/io/filesystem/gcs/gcs.go:167

		client, err = gcsx.NewUnauthenticatedClient(ctx)
		if err != nil {
			panic(errors.Wrapf(err, "failed to create GCS client"))
		}
	}
	return &fs{
		client: client,
	}
}

func SetRequesterBillingProject(project string) {
	billingProject = project
}

// RequesterBillingProject configure project to be used in google storage operations
// with requester pays actived. More informaiton about requester pays in https://cloud.google.com/storage/docs/requester-pays
func RequesterBillingProject(project string) error {
	if project == "" {
		return fmt.Errorf("project cannot be empty, got %v", project)
	}
	// The hook itself is defined in beam/core/runtime/harness/file_system_hooks.go
	return hooks.EnableHook(projectBillingHook, project)
}

func (f *fs) Close() error {
	return f.client.Close()
}

func (f *fs) List(ctx context.Context, glob string) ([]string, error) {
	bucket, object, err := gcsx.ParseObject(glob)
	if err != nil {
		return nil, err
	}

	// Compile the glob pattern to a regex. We use a custom glob-to-regex
	// translation that treats / as a regular character (not a separator),
	// since GCS object names are flat. This also supports ** for recursive

View on GitHub (pinned to 12126d8942)