apache/beam · error

invalid staging location

Error message

invalid staging location %v

What it means

upload validates the staging destination with gcsx.ParseObject before creating a storage client. ParseObject requires a URL that parses and has the 'gs' scheme plus a non-empty bucket (host). Any staging location that is not a well-formed gs://bucket/path string is rejected with this wrapped error.

Solutions

  1. Set --staging_location to a full valid GCS path: gs://<bucket>/<prefix>, e.g. gs://my-bucket/staging.
  2. Ensure the location starts with the exact 'gs://' scheme and names an existing bucket you can write to.
  3. Verify with gcsx.ParseObject locally before submitting: bucket, obj, err := gcsx.ParseObject(location).
  4. If using temp_location too, confirm it is also a gs:// URL, not a local dir.

Example fix

// before
--staging_location=./build/staging
// after
--staging_location=gs://my-project-bucket/staging
Defensive patterns

Strategy: validation

Validate before calling

bucket, obj, err := gcsx.ParseObject(stagingLocation)
if err != nil {
    return fmt.Errorf("--staging_location must be gs://bucket/path, got %q: %w", stagingLocation, err)
}

Prevention

When it happens

Trigger: StageModel or stageFile calls upload with an object string whose scheme is not 'gs' (e.g. a local path like ./staging, an https:// URL, or 'gs://' with no bucket).

Common situations: The --staging_location flag was set to an S3/https/local path or omitted/defaulted incorrectly; a trailing typo like 'gcs://bucket/obj'; missing bucket after 'gs://'; case sensitivity in 'gs'.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/runners/dataflow/dataflowlib/stage.go:58

	fd, err := os.Open(filename)
	if err != nil {
		return "", errors.Wrapf(err, "failed to open file %s", filename)
	}
	defer fd.Close()

	sha256W := sha256.New()
	tee := io.TeeReader(fd, sha256W)
	if err := upload(ctx, project, url, tee); err != nil {
		return "", err
	}
	hash := hex.EncodeToString(sha256W.Sum(nil))
	return hash, nil
}

func upload(ctx context.Context, project, object string, r io.Reader) error {
	bucket, obj, err := gcsx.ParseObject(object)
	if err != nil {
		return errors.Wrapf(err, "invalid staging location %v", object)
	}
	client, err := gcsx.NewClient(ctx, storage.ScopeReadWrite)
	if err != nil {
		return err
	}
	_, err = gcsx.Upload(ctx, client, project, bucket, obj, r)
	return err
}

// ResolveXLangArtifacts resolves cross-language artifacts with a given GCS
// URL as a destination, and then stages all local artifacts to that URL. This
// function returns a list of staged artifact URLs.
func ResolveXLangArtifacts(ctx context.Context, edges []*graph.MultiEdge, project, url string) ([]string, error) {
	cfg := xlangx.ResolveConfig{
		SdkPath: url,
		JoinFn: func(url, name string) string {
			return gcsx.Join(url, "/", name)
		},

View on GitHub (pinned to 12126d8942)