apache/beam · error
expected single value map, had
Error message
expected single value map, had %v - %v
What it means
getOnlyPair is a generic helper asserting a map has exactly one entry (used e.g. to fetch the single input/output of a transform). If the map has zero or multiple entries, prism panics with the length and full map contents because the expected structural invariant of the pipeline graph is violated.
Solutions
- Identify the transform from the map contents in the panic and check its expected input/output arity.
- Ensure transforms consuming this helper (like Combine) are not given additional side inputs.
- Inspect the expanded pipeline JSON to see why the map has multiple entries; restructure the pipeline accordingly.
- File a Beam issue if a standard transform triggers it — likely a graph-construction bug.
Example fix
// before pc := beam.ParDo(s, fn, input, other) // adds extra input edge breaking single-input assumption // after res := beam.Combine(s, fn, input) // keep the combine single-input
Defensive patterns
Strategy: validation
Validate before calling
// Check map arity before calling getOnlyPair
if len(inputs) != 1 {
return fmt.Errorf("expected single input, got %d", len(inputs))
} Type guard
func isSingleEntry[K comparable, V any](m map[K]V) bool { return len(m) == 1 } Try / catch
func safeGetOnlyPair[K comparable, V any](m map[K]V) (k K, v V, recovered any) {
defer func() { recovered = recover() }()
k, v = getOnlyPair(m)
return
} Prevention
- Don't add side inputs to transforms assumed single-input
- Inspect expansion output for unexpected extra edges
- Validate pipeline graph arity before submission
When it happens
Trigger: getOnlyValue (or getOnlyPair) is called on a transform's inputs/outputs map that contains 0 or 2+ PCollection IDs — e.g. a Combine or other transform expected to be single-input/single-output but wired with extra side inputs or multiple outputs.
Common situations: Composite transforms producing unexpected arity, cross-language expansion yielding extra edges, or pipeline graph anomalies from optimizer/sibling-runner submissions.
Related errors
- panic(err) propagating lpUnknownCoders error
- unreachable
- broken invariant: idsFound map is nil, but idsRequired map…
- computeFacts: two producers for one PCollection
- Creating CustomCoder for type failed
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/570666f925f46b05.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/runners/prism/internal/execute.go:425
c := coders[coldCId]
if c.GetSpec().GetUrn() == urns.CoderKV {
return c.GetComponentCoderIds()[0], true
}
return "", false
}
func getWindowValueCoders(comps *pipepb.Components, col *pipepb.PCollection, coders map[string]*pipepb.Coder) (engine.WinCoderType, exec.WindowDecoder, exec.WindowEncoder) {
ws := comps.GetWindowingStrategies()[col.GetWindowingStrategyId()]
wcID, err := lpUnknownCoders(ws.GetWindowCoderId(), coders, comps.GetCoders())
if err != nil {
panic(err)
}
return makeWindowCoders(coders[wcID])
}
func getOnlyPair[K comparable, V any](in map[K]V) (K, V) {
if len(in) != 1 {
panic(fmt.Sprintf("expected single value map, had %v - %v", len(in), in))
}
for k, v := range in {
return k, v
}
panic("unreachable")
}
func getOnlyValue[K comparable, V any](in map[K]V) V {
_, v := getOnlyPair(in)
return v
}
// buildTrigger converts the protocol buffer representation of a trigger
// to the engine representation.
func buildTrigger(tpb *pipepb.Trigger) engine.Trigger {
switch at := tpb.GetTrigger().(type) {
case *pipepb.Trigger_AfterAll_:
subTriggers := make([]engine.Trigger, 0, len(at.AfterAll.GetSubtriggers()))View on GitHub (pinned to 12126d8942)