{"record":{"id":"e3313dc6ca04d683","repo":"apache/beam","slug":"multiple-locations-for-v-v","errorCode":null,"errorMessage":"multiple locations for %v:%v","messagePattern":"multiple locations for (.+?):(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/artifact/gcsproxy/retrieval.go","lineNumber":136,"sourceCode":"\t}\n\treturn nil\n}\n\nfunc validate(md *jobpb.ProxyManifest) error {\n\tkeys := make(map[string]bool)\n\tfor _, a := range md.GetManifest().GetArtifact() {\n\t\tif _, seen := keys[a.Name]; seen {\n\t\t\treturn errors.Errorf(\"multiple artifact with name %v\", a.Name)\n\t\t}\n\t\tkeys[a.Name] = true\n\t}\n\tfor _, l := range md.GetLocation() {\n\t\tfresh, seen := keys[l.Name]\n\t\tif !seen {\n\t\t\treturn errors.Errorf(\"no artifact named %v for location %v\", l.Name, l.Uri)\n\t\t}\n\t\tif !fresh {\n\t\t\treturn errors.Errorf(\"multiple locations for %v:%v\", l.Name, l.Uri)\n\t\t}\n\t\tkeys[l.Name] = false\n\t}\n\n\tfor key, fresh := range keys {\n\t\tif fresh {\n\t\t\treturn errors.Errorf(\"no location for %v\", key)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc parseObject(blob string) (string, string) {\n\tbucket, object, err := gcsx.ParseObject(blob)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn bucket, object","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/artifact/gcsproxy/retrieval.go#L118-L154","documentation":"validate enforces a 1:1 mapping between artifact names and locations; once a location for a name is seen, the name is marked not-fresh, and a second location with the same name triggers this error. Raised during NewRetrievalServer.","triggerScenarios":"Two or more md.GetLocation() entries carry the same Name while the corresponding artifact appears only once in the manifest (the !fresh branch of validate).","commonSituations":"Same artifact registered at multiple URIs by a staging bug; duplicated location entries after merging manifests; copy-paste of a location block when hand-assembling the manifest.","solutions":["Keep exactly one Location per artifact Name; drop duplicate location entries.","Deduplicate locations by Name before constructing the ProxyManifest.","Regenerate the manifest via CommitManifest rather than manual assembly."],"exampleFix":"// before\nlocs := append(locs, &jobpb.Location{Name: \"x\", Uri: uriA}, &jobpb.Location{Name: \"x\", Uri: uriB})\n// after\nlocs := append(locs, &jobpb.Location{Name: \"x\", Uri: uriA}) // one location per artifact name","handlingStrategy":"validation","validationCode":"func locationNamesUnique(md *jobpb.ProxyManifest) error {\n\tseen := map[string]bool{}\n\tfor _, l := range md.GetLocation() {\n\t\tif seen[l.Name] {\n\t\t\treturn fmt.Errorf(\"duplicate location for %v\", l.Name)\n\t\t}\n\t\tseen[l.Name] = true\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"if err := gcsproxy.NewRetrievalServer(manifestPath); err != nil {\n\tif strings.Contains(err.Error(), \"multiple locations for\") {\n\t\t// deduplicate location entries and re-commit the manifest\n\t}\n}","preventionTips":["Key locations by artifact name in a map when building the manifest.","Don't merge manifests by concatenating location lists.","One GCS URI per artifact name; store alternates elsewhere."],"tags":["validation","manifest","protobuf"],"backgroundTag":"schema-validation-failed","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"}