apache/beam · error

mismatched number of named outputs: received - %v expected -

Error message

mismatched number of named outputs:
received - %v
expected - %v

What it means

VerifyNamedOutputs checks that a cross-language transform's expanded outputs match the external transform's expected outputs map. This panic fires when the number of outputs produced by the expanded (remote) transform differs from the number in ext.OutputsMap.

Source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/xlang.go:135

		outputs := t.GetOutputs()
		for tag, nodeID := range outputs {
			if pcolID, exists := idxMap[nodeID]; exists {
				outputs[tag] = pcolID
			}
		}
	}
}

// VerifyNamedOutputs ensures the expanded outputs correspond to the correct and expected named outputs
func VerifyNamedOutputs(ext *graph.ExternalTransform) {
	transform, err := ExpandedTransform(ext.Expanded)
	if err != nil {
		panic(err)
	}
	expandedOutputs := transform.GetOutputs()

	if len(expandedOutputs) != len(ext.OutputsMap) {
		panic(errors.Errorf("mismatched number of named outputs:\nreceived - %v\nexpected - %v", len(expandedOutputs), len(ext.OutputsMap)))
	}

	for tag := range ext.OutputsMap {
		_, exists := expandedOutputs[tag]
		if tag != graph.UnnamedOutputTag && !exists {
			panic(errors.Errorf("missing named output in expanded transform: %v is expected in %v", tag, expandedOutputs))
		}
		if tag == graph.UnnamedOutputTag && len(expandedOutputs) > 1 {
			panic(errors.Errorf("mismatched number of unnamed outputs:\nreceived - %v\nexpected - 1", len(expandedOutputs)))
		}
	}
}

// ResolveOutputIsBounded updates each Output node with respect to the received
// expanded components to reflect if it is bounded or not
func ResolveOutputIsBounded(e *graph.MultiEdge, isBoundedUpdater func(*graph.Node, bool)) {
	ext := e.External
	exp := ext.Expanded

View on GitHub (pinned to 12126d8942)

Solutions

  1. Align the number of beam.CrossTransform outputs with the transform's actual outputs in the expansion service.
  2. Restart/update the expansion service so its transform version matches the client SDK.
  3. Check expansion logs to confirm the expanded transform's output tags and adjust the OutputsMap.

Example fix

// before
x := xlang.CrossTransform(scope, ext, xlang.UnderlyingMethod("v1"), xlang.Output("out", "a"))
// after
x := xlang.CrossTransform(scope, ext, xlang.UnderlyingMethod("v1"), xlang.Output("out", "a"), xlang.Output("out2", "b"))
Defensive patterns

Strategy: validation

Validate before calling

if got, want := len(expandedOutputs), len(outputsMap); got != want {
    return fmt.Errorf("expansion returned %d outputs, declared %d", got, want)
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Fatalf("cross-language expansion mismatch: %v", r)
    }
}()

Prevention

When it happens

Trigger: Calling TryCrossLanguage/Expand for an external transform whose expansion response from the expansion service returns a different count of output PCollections than the tags declared by beam.CrossTransform/Output calls.

Common situations: Expansion service serving a different version of the transform than the local SDK expects; declaring fewer/more named outputs than the transform actually emits; stale expansion service jar/container.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/b7dd3d5fc526d20c. Report an issue: GitHub.