apache/beam · error
mismatch'd counts between External tags (%v) and inputs (%v)
Error message
mismatch'd counts between External tags (%v) and inputs (%v)
What it means
For graph.External edges, the External payload declares an InputsMap of tags. If the number of tags in InputsMap doesn't equal the number of actual input edges on the graph node, the mapping is inconsistent and addMultiEdge aborts via handleErr, reporting both counts.
Source
Thrown at sdks/go/pkg/beam/core/runtime/graphx/translate.go:690
spec = &pipepb.FunctionSpec{Urn: URNGBK}
case graph.WindowInto:
windowFn, err := makeWindowFn(edge.Edge.WindowFn)
if err != nil {
return handleErr(err)
}
payload := &pipepb.WindowIntoPayload{
WindowFn: windowFn,
}
spec = &pipepb.FunctionSpec{Urn: URNWindow, Payload: protox.MustEncode(payload)}
case graph.External:
pyld := edge.Edge.Payload
spec = &pipepb.FunctionSpec{Urn: pyld.URN, Payload: pyld.Data}
if len(pyld.InputsMap) != 0 {
if got, want := len(pyld.InputsMap), len(edge.Edge.Input); got != want {
return handleErr(errors.Errorf("mismatch'd counts between External tags (%v) and inputs (%v)", got, want))
}
inputs = make(map[string]string)
for tag, in := range InboundTagToNode(pyld.InputsMap, edge.Edge.Input) {
if _, err := m.addNode(in); err != nil {
return handleErr(err)
}
inputs[tag] = nodeID(in)
}
}
if len(pyld.OutputsMap) != 0 {
if got, want := len(pyld.OutputsMap), len(edge.Edge.Output); got != want {
return handleErr(errors.Errorf("mismatch'd counts between External tags (%v) and outputs (%v)", got, want))
}
outputs = make(map[string]string)
for tag, out := range OutboundTagToNode(pyld.OutputsMap, edge.Edge.Output) {
if _, err := m.addNode(out); err != nil {
return handleErr(err)View on GitHub (pinned to 12126d8942)
Solutions
- Rebuild the External transform with a correctly sized InputsMap matching the input count
- Regenerate the external payload with a matching SDK/runner version
- Check InboundTagToNode inputs: each tag must correspond to one edge input
- If hand-writing cross-language transforms, verify tag names and counts in the payload
Example fix
// before
pyld := graph.Payload{URN: urn, InputsMap: map[string]int{"a":0}} // 1 tag, 2 inputs
// after
pyld := graph.Payload{URN: urn, InputsMap: map[string]int{"a":0,"b":1}} Defensive patterns
Strategy: validation
Validate before calling
// Before marshalling external transforms, validate tag/input arity
if len(pyld.InputsMap) != 0 && len(pyld.InputsMap) != len(edge.Input) {
return fmt.Errorf("external %q: %d tags vs %d inputs", pyld.URN, len(pyld.InputsMap), len(edge.Input))
} Try / catch
if _, err := graphx.Marshal(p); err != nil {
if strings.Contains(err.Error(), "External tags") && strings.Contains(err.Error(), "inputs") {
return fmt.Errorf("external transform payload inconsistent: %v", err)
}
return err
} Prevention
- Generate external payloads with the same SDK version used for marshalling
- Count inputs/outputs of cross-language transforms when defining tags
- Test cross-language pipelines end-to-end in CI
When it happens
Trigger: Marshalling a pipeline containing an External transform (cross-language / expansion payload) whose pyld.InputsMap length differs from len(edge.Edge.Input) — e.g. the external payload was constructed with mismatched tag lists.
Common situations: Building External transforms by hand with wrong inputs map; cross-language transforms whose payload was generated by an older runner SDK; custom I/O connectors with changed arity between versions.
Related errors
- mismatch'd counts between External tags (%v) and outputs (%v
- failed to expand cross language transform for edge: %v
- res.GetError()
- invalid scope
- unknown atomic type: %v
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/20322e01561ec8f5.
Report an issue: GitHub.