{"record":{"id":"39652df4ba0be046","repo":"apache/beam","slug":"multiple-artifact-with-name-v","errorCode":null,"errorMessage":"multiple artifact with name %v","messagePattern":"multiple artifact with name (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/artifact/gcsproxy/retrieval.go","lineNumber":126,"sourceCode":"\t\t\tif err := stream.Send(&jobpb.ArtifactChunk{Data: data[:n]}); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"chunk send failed\")\n\t\t\t}\n\t\t}\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to read from %v\", blob)\n\t\t}\n\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}","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/artifact/gcsproxy/retrieval.go#L108-L144","documentation":"validate rejects a ProxyManifest whose artifact list contains two entries with the same Name, since artifact names must be unique keys for retrieval lookup. The error is raised at server construction (NewRetrievalServer), before serving any requests.","triggerScenarios":"NewRetrievalServer is called with a manifest md where md.GetManifest().GetArtifact() contains two or more artifacts sharing the same Name field.","commonSituations":"A buggy staging pipeline appends the same artifact twice to the Manifest proto; manual assembly of ProxyManifest JSON/proto duplicates entries; merge of two manifests without deduplicating artifact names.","solutions":["Deduplicate artifacts by Name before building/committing the ProxyManifest.","Regenerate the manifest via the standard staging path (CommitManifest) instead of hand-crafting it.","If merging manifests, key artifacts by Name in a map so later entries overwrite earlier ones.","Check the staging server code for repeated calls to AddArtifacts-like APIs for the same file."],"exampleFix":"// before\nartifacts := append(manifest.GetArtifact(), art)\n// after\nseen := map[string]bool{}\nvar artifacts []*pipepb.Artifact\nfor _, a := append(manifest.GetArtifact(), art) {\n\tif !seen[a.Name] {\n\t\tseen[a.Name] = true\n\t\tartifacts = append(artifacts, a)\n\t}\n}","handlingStrategy":"validation","validationCode":"func artifactNamesUnique(md *jobpb.ProxyManifest) error {\n\tseen := map[string]bool{}\n\tfor _, a := range md.GetManifest().GetArtifact() {\n\t\tif seen[a.Name] {\n\t\t\treturn fmt.Errorf(\"duplicate artifact %v\", a.Name)\n\t\t}\n\t\tseen[a.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 artifact with name\") {\n\t\t// rebuild/deduplicate the manifest and re-upload\n\t}\n}","preventionTips":["Deduplicate artifacts by Name whenever assembling or merging manifests.","Always build manifests through CommitManifest rather than by hand.","Add a validate() call before uploading any ProxyManifest."],"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"}