apache/beam · critical
outputTypes already set as: %v
Error message
outputTypes already set as: %v
What it means
ExternalTransform.WithNamedOutputs sets the tag→output-index map for cross-language transforms. Like WithNamedInputs it may only be called once; a second call when OutputsMap is already set panics with 'outputTypes already set as: ...'.
Source
Thrown at sdks/go/pkg/beam/core/graph/xlang.go:90
Expanded *ExpandedTransform
}
// WithNamedInputs adds a map (tag -> index of Inbound in MultiEdge.Input)
// of named inputs corresponsing to ExternalTransform's InputsMap
func (ext ExternalTransform) WithNamedInputs(inputsMap map[string]int) ExternalTransform {
if ext.InputsMap != nil {
panic(errors.Errorf("inputs already set as: \n%v", ext.InputsMap))
}
ext.InputsMap = inputsMap
return ext
}
// WithNamedOutputs adds a map (tag -> index of Outbound in MultiEdge.Output)
// of named outputs corresponsing to ExternalTransform's OutputsMap
func (ext ExternalTransform) WithNamedOutputs(outputsMap map[string]int) ExternalTransform {
if ext.OutputsMap != nil {
panic(errors.Errorf("outputTypes already set as: \n%v", ext.OutputsMap))
}
ext.OutputsMap = outputsMap
return ext
}
// NewNamespaceGenerator returns a functions that generates a random string of n alphabets
func NewNamespaceGenerator(n int) func() string {
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
letterIDBits = 6 // 6 bits to represent a letter index
letterIDMask = 1<<letterIDBits - 1 // All 1-bits, as many as letterIDBits
letterIDMax = 63 / letterIDBits // # of letter indices fitting in 63 bits
)
var src = rand.NewSource(time.Now().UnixNano())
random := func() string {
sb := strings.Builder{}View on GitHub (pinned to 12126d8942)
Solutions
- Call WithNamedOutputs exactly once per ExternalTransform; remove the redundant call.
- Construct a new ExternalTransform if a different output map must be applied.
- Condition the call on `ext.OutputsMap == nil` in builder helpers.
- Use the panic's printed existing map to identify and reconcile the conflicting call site.
Example fix
// before ext = ext.WithNamedOutputs(outs) ext = ext.WithNamedOutputs(outs2) // panics // after ext = ext.WithNamedOutputs(outs)
Defensive patterns
Strategy: validation
Validate before calling
if ext.OutputsMap == nil {
ext = ext.WithNamedOutputs(outputsMap)
} Try / catch
func safeWithOutputs(ext graph.ExternalTransform, m map[string]int) (r graph.ExternalTransform) {
defer func() { if rec := recover(); rec != nil { log.Printf("outputs already set: %v", rec) } }()
return ext.WithNamedOutputs(m)
} Prevention
- Call WithNamedOutputs once per ExternalTransform, ideally at construction time.
- Create a fresh ExternalTransform when a different output map is needed.
When it happens
Trigger: Calling WithNamedOutputs twice on the same ExternalTransform (duplicate builder invocation), before the transform is expanded into the graph.
Common situations: Chaining builder calls in two places (helper + caller); re-running construction logic on a retained ExternalTransform; copy-paste duplication when wiring multi-output external transforms.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- inputs already set as: %v
- invalid bundle processing state: %d
- error in startAutomatedJavaExpansionService(%s,%s): %w
- error in starting expansion service, StartService(): %w
- panic in ElementManager.Bundles watermark evaluation gorouti
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/ffcc98d7a14b3bcc.
Report an issue: GitHub.