apache/beam · error

panic(err)

Error message

panic(err)

What it means

Join parses a gs:// object path and appends path elements, preserving the prefix; if ParseObject fails (the object is not a valid gs:// path) Join panics with the parse error. It treats an invalid GCS URL as an unrecoverable construction mistake.

Solutions

  1. Pass a well-formed gs://bucket/path string to Join (or MakeObject output)
  2. Validate the path with ParseObject first and handle its error instead of panicking
  3. If non-GCS paths are possible, branch on prefix before calling Join
  4. Normalize the path (prepend "gs://" + bucket) when the prefix may have been stripped

Example fix

// before
out := gcsx.Join(gcsPath, "results") // panics if gcsPath invalid
// after
if _, _, err := gcsx.ParseObject(gcsPath); err != nil {
	return fmt.Errorf("invalid GCS path %q: %w", gcsPath, err)
}
out := gcsx.Join(gcsPath, "results")
Defensive patterns

Strategy: validation

Validate before calling

if !strings.HasPrefix(object, "gs://") {
	return fmt.Errorf("expected gs:// path, got %q", object)
}

Type guard

func isGCSPath(s string) bool { _, _, err := gcsx.ParseObject(s); return err == nil }

Try / catch

defer func() {
	if r := recover(); r != nil {
		err = fmt.Errorf("invalid GCS object %q: %v", object, r)
	}
}()

Prevention

When it happens

Trigger: Calling gcsx.Join with a string that lacks the gs:// prefix or has no bucket (e.g. Join("s3://x/y", "a"), Join("", "log.txt"), Join("plain/path", "a")) — ParseObject returns an error and Join panics.

Common situations: Users passing AWS S3 or local filesystem paths to a Beam GCS utility; a bucket variable defaulting to empty; stripping the gs:// prefix upstream and passing the remainder to Join.

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/917ea2742cc93bf0. Report an issue: GitHub.

Appendix: source

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

		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 == "" {
		return parsed.Host, "", nil
	}

	// remove leading "/" in URL path
	return parsed.Host, parsed.Path[1:], nil
}

// Join joins a GCS path with an element. Preserves
// the gs:// prefix.
func Join(object string, elms ...string) string {
	bucket, prefix, err := ParseObject(object)
	if err != nil {
		panic(err)
	}
	return MakeObject(bucket, path.Join(prefix, path.Join(elms...)))
}

View on GitHub (pinned to 12126d8942)