{"record":{"id":"7b96a8bab7bbaa24","repo":"apache/beam","slug":"object-s-must-have-gs-scheme","errorCode":null,"errorMessage":"object %s must have 'gs' scheme","messagePattern":"object (.+?) must have 'gs' scheme","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/util/gcsx/gcs.go","lineNumber":142,"sourceCode":"// MakeObject creates a object location from bucket and path. For example,\n// MakeObject(\"foo\", \"bar/baz\") returns \"gs://foo/bar/baz\". The bucket\n// must be non-empty.\nfunc MakeObject(bucket, path string) string {\n\tif bucket == \"\" {\n\t\tpanic(\"bucket must be non-empty\")\n\t}\n\treturn fmt.Sprintf(\"gs://%v/%v\", bucket, path)\n}\n\n// ParseObject deconstructs a GCS object name into (bucket, name).\nfunc ParseObject(object string) (bucket, path string, err error) {\n\tparsed, err := url.Parse(object)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\n\tif parsed.Scheme != \"gs\" {\n\t\treturn \"\", \"\", errors.Errorf(\"object %s must have 'gs' scheme\", object)\n\t}\n\tif parsed.Host == \"\" {\n\t\treturn \"\", \"\", errors.Errorf(\"object %s must have bucket\", object)\n\t}\n\tif parsed.Path == \"\" {\n\t\treturn parsed.Host, \"\", nil\n\t}\n\n\t// remove leading \"/\" in URL path\n\treturn parsed.Host, parsed.Path[1:], nil\n}\n\n// Join joins a GCS path with an element. Preserves\n// the gs:// prefix.\nfunc Join(object string, elms ...string) string {\n\tbucket, prefix, err := ParseObject(object)\n\tif err != nil {\n\t\tpanic(err)","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/util/gcsx/gcs.go#L124-L160","documentation":"gcsx.ParseObject parses a GCS object URL and requires the 'gs' scheme. This error is returned when the given object string parses as a URL but its scheme is not 'gs' (e.g. 's3://...', 'https://...', or a bare path). Callers like List, OpenRead, staging/retrieval servers reject the path before touching GCS.","triggerScenarios":"Passing an object string with a non-gs scheme (http://, s3://, /local/path) to gcsx.List, gcsx.OpenRead, ParseObject, NewStagingServer/NewRetrievalServer manifest paths, or ReadProxyManifest.","commonSituations":"Config mistakes: pointing staging/manifest options at local paths or other cloud URLs, forgetting the gs:// prefix, or copy-pasting an HTTPS console URL instead of the gs:// URI.","solutions":["Use the full gs://bucket/object URI, e.g. 'gs://my-bucket/path/obj'","If the source is another provider, migrate/download the object to GCS first","Validate the scheme in your config before calling the library"],"exampleFix":"// before\ngcsx.OpenRead(ctx, client, \"https://storage.googleapis.com/my-bucket/obj\")\n// after\ngcsx.OpenRead(ctx, client, \"gs://my-bucket/obj\")","handlingStrategy":"validation","validationCode":"u, err := url.Parse(obj)\nif err != nil || u.Scheme != \"gs\" {\n\treturn fmt.Errorf(\"need gs:// URI, got %q\", obj)\n}","typeGuard":"func isGCSURI(s string) bool {\n\tu, err := url.Parse(s)\n\treturn err == nil && u.Scheme == \"gs\"\n}","tryCatchPattern":"if err != nil {\n\tif strings.Contains(err.Error(), \"must have 'gs' scheme\") {\n\t\treturn fmt.Errorf(\"invalid GCS path %q: prefix with gs://\", obj)\n\t}\n\treturn err\n}","preventionTips":["Always construct GCS paths with the gs:// prefix","Never use HTTPS console URLs as storage paths","Validate URI scheme in config loading"],"tags":["gcs","url","validation","apache-beam"],"backgroundTag":"invalid-url","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}