{"record":{"id":"4218e61509a04e62","repo":"apache/beam","slug":"multiple-worker-ids-in-metadata-v","errorCode":null,"errorMessage":"multiple worker ids in metadata: %v","messagePattern":"multiple worker ids in metadata: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/util/grpcx/metadata.go","lineNumber":39,"sourceCode":"\n\t\"github.com/apache/beam/sdks/v2/go/pkg/beam/internal/errors\"\n\t\"google.golang.org/grpc/metadata\"\n)\n\nconst idKey = \"worker_id\"\n\n// ReadWorkerID reads the worker ID from an incoming gRPC request context.\nfunc ReadWorkerID(ctx context.Context) (string, error) {\n\tmd, ok := metadata.FromIncomingContext(ctx)\n\tif !ok {\n\t\treturn \"\", errors.New(\"failed to read metadata from context\")\n\t}\n\tid, ok := md[idKey]\n\tif !ok || len(id) < 1 {\n\t\treturn \"\", errors.Errorf(\"failed to find worker id in metadata %v\", md)\n\t}\n\tif len(id) > 1 {\n\t\treturn \"\", errors.Errorf(\"multiple worker ids in metadata: %v\", id)\n\t}\n\treturn id[0], nil\n}\n\n// WriteWorkerID write the worker ID to an outgoing gRPC request context. It\n// merges the information with any existing gRPC metadata.\nfunc WriteWorkerID(ctx context.Context, id string) context.Context {\n\tmd := metadata.New(map[string]string{\n\t\tidKey: id,\n\t})\n\tif old, ok := metadata.FromOutgoingContext(ctx); ok {\n\t\tmd = metadata.Join(md, old)\n\t}\n\treturn metadata.NewOutgoingContext(ctx, md)\n}\n","sourceCodeStart":21,"sourceCodeEnd":55,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/util/grpcx/metadata.go#L21-L55","documentation":"ReadWorkerID extracts the worker ID from incoming gRPC metadata under the idKey. The Apache Beam Go SDK writes exactly one worker ID per request, so finding more than one value means the metadata is malformed and cannot be safely interpreted.","triggerScenarios":"Calling ReadWorkerID (directly or via workerFromMetadataCtx) on a context whose incoming gRPC metadata contains 2+ values for the worker-id key, e.g. md[idKey] has len > 1.","commonSituations":"A proxy or intermediary merging metadata and duplicating the worker-id key; a client calling WriteWorkerID twice on the same context incorrectly; hand-crafted metadata in tests or custom transports appending the key multiple times.","solutions":["Inspect the outgoing client code and ensure WriteWorkerID is applied only once per request context.","Check any gRPC proxy/interceptor for duplicate metadata key injection and deduplicate the worker-id key.","Fix test/setup code that constructs metadata manually to include the id key exactly once (use a []string of length 1)."],"exampleFix":"// before\nmd := metadata.Pairs(\"beam:worker:id\", \"a\", \"beam:worker:id\", \"b\")\n// after\nmd := metadata.Pairs(\"beam:worker:id\", \"a\")","handlingStrategy":"validation","validationCode":"md, _ := metadata.FromIncomingContext(ctx)\nids := md[\"beam:worker:id\"] // idKey\nif len(ids) != 1 { /* fix metadata before calling ReadWorkerID */ }","typeGuard":"func hasSingleWorkerID(md metadata.MD, key string) bool { return len(md.Get(key)) == 1 }","tryCatchPattern":null,"preventionTips":["Apply WriteWorkerID exactly once per outgoing context.","Audit proxies/interceptors for duplicate metadata key injection.","In tests, build metadata with a single-element value slice."],"tags":["grpc","metadata","worker-id"],"backgroundTag":"invalid-argument-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"}