{"record":{"id":"83a5ba077589e7d2","repo":"apache/beam","slug":"location-v-is-not-a-gcs-object","errorCode":null,"errorMessage":"location %v is not a GCS object","messagePattern":"location (.+?) is not a GCS object","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/artifact/gcsproxy/retrieval.go","lineNumber":69,"sourceCode":"\t}\n\tvar md jobpb.ProxyManifest\n\tif err := proto.Unmarshal(content, &md); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"invalid manifest %v\", object)\n\t}\n\treturn &md, nil\n}\n\n// NewRetrievalServer creates a artifact retrieval server for the\n// given manifest. It requires that the locations are in GCS.\nfunc NewRetrievalServer(md *jobpb.ProxyManifest) (*RetrievalServer, error) {\n\tif err := validate(md); err != nil {\n\t\treturn nil, err\n\t}\n\n\tblobs := make(map[string]string)\n\tfor _, l := range md.GetLocation() {\n\t\tif _, _, err := gcsx.ParseObject(l.GetUri()); err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"location %v is not a GCS object\", l.GetUri())\n\t\t}\n\t\tblobs[l.GetName()] = l.GetUri()\n\t}\n\treturn &RetrievalServer{md: md.GetManifest(), blobs: blobs}, nil\n}\n\n// GetManifest returns the manifest for all artifacts.\nfunc (s *RetrievalServer) GetManifest(ctx context.Context, req *jobpb.GetManifestRequest) (*jobpb.GetManifestResponse, error) {\n\treturn &jobpb.GetManifestResponse{Manifest: s.md}, nil\n}\n\n// GetArtifact returns a given artifact.\nfunc (s *RetrievalServer) GetArtifact(req *jobpb.LegacyGetArtifactRequest, stream jobpb.LegacyArtifactRetrievalService_GetArtifactServer) error {\n\tkey := req.GetName()\n\tblob, ok := s.blobs[key]\n\tif !ok {\n\t\treturn errors.Errorf(\"artifact %v not found\", key)\n\t}","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/artifact/gcsproxy/retrieval.go#L51-L87","documentation":"NewRetrievalServer validates every artifact location in the manifest is a GCS object by parsing each URI. This wrapped error is returned when any location URI in the ProxyManifest cannot be parsed as a GCS bucket/object pair.","triggerScenarios":"Building a retrieval server from a manifest whose Location entries contain non-GCS URIs (local file paths, https URLs, empty strings) via NewRetrievalServer(ctx, md).","commonSituations":"Manifests produced by non-GCS artifact proxies, hand-edited manifests, or URIs missing the gs:// prefix.","solutions":["Correct the manifest so every location uri is a valid gs://bucket/object path.","Regenerate the manifest with a GCS-backed staging/proxy pipeline.","Pre-validate each URI with gcsx.ParseObject before constructing the server to fail fast with a clearer message."],"exampleFix":"// before\nLocation: &jobpb.ArtifactMetadata{Uri: \"/tmp/artifact.bin\"}\n// after\nLocation: &jobpb.ArtifactMetadata{Uri: \"gs://my-bucket/artifacts/artifact.bin\"}","handlingStrategy":"validation","validationCode":"for _, l := range md.GetLocation() {\n    if _, _, err := gcsx.ParseObject(l.GetUri()); err != nil {\n        return fmt.Errorf(\"location %q is not gs://bucket/object\", l.GetUri())\n    }\n}","typeGuard":"func isGCSLocation(l *jobpb.Location) bool { _, _, err := gcsx.ParseObject(l.GetUri()); return err == nil }","tryCatchPattern":"srv, err := NewRetrievalServer(ctx, md)\nif err != nil { return fmt.Errorf(\"manifest has non-GCS locations: %w\", err) }","preventionTips":["Ensure all artifact URIs use the gs:// scheme before building the server.","Validate manifests at write time so bad URIs never reach NewRetrievalServer."],"tags":["gcs","url","validation","beam"],"backgroundTag":"invalid-url-format","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"}