apache/beam · error
Unexpected composite type
Error message
Unexpected composite type: %v
What it means
inferCoder in sdks/go/pkg/beam/coder.go panics with "Unexpected composite type: %v" when it encounters a composite (multi-component) FullType whose kind is not one of the supported composite kinds (KV, CoGBK, WindowedValue, ShardedKey, etc.). This is a defensive programmer-error panic: the Beam type system should have rejected the type earlier, so reaching the default branch means an unhandled typex kind reached coder inference. It aborts pipeline construction immediately.
Solutions
- Identify the kind from the panic message; if it is a custom or unsupported kind, change the PCollection element type to a supported one (KV, struct, slice, etc.).
- Align the Beam SDK version so inferCoder knows the composite kind (it was likely added in a newer release).
- If you maintain a fork, add a case to inferCoder mapping the missing kind to the correct coder.Coder Kind.
- Isolate which transform introduced the type and adjust its type hints.
Example fix
// before
default:
panic(fmt.Sprintf("Unexpected composite type: %v", t))
// after
case typex.MyCustomKind:
return &coder.Coder{Kind: coder.MyCustomKind, T: t, Components: c}, nil
default:
panic(fmt.Sprintf("Unexpected composite type: %v", t)) Defensive patterns
Strategy: validation
Validate before calling
if t == nil || !isSupportedKind(t.Kind()) {
return nil, fmt.Errorf("unsupported composite type for coder inference: %v", t)
}
c, err := beam.NewCoder(t.Type())
if err != nil {
return nil, err
} Type guard
func isSupportedKind(k typex.Kind) bool {
switch k {
case typex.KVKind, typex.CoGBKKind, typex.WindowedValueKind, typex.ShardedKeyKind:
return true
}
return false
} Try / catch
func inferCoderSafe(t typex.FullType) (c *coder.Coder, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("coder inference panicked for type %v: %v", t, r)
}
}()
return beam.NewCoder(t.Type())
} Prevention
- Only use typex kinds enumerated by the installed Beam release in element types.
- Keep the Beam SDK version identical across pipeline construction and workers.
- Add a unit test calling beam.NewCoder for every element type your pipeline uses.
- Pin Beam dependencies so upgrades cannot introduce unknown composite kinds silently.
When it happens
Trigger: Calling NewElementEncoder, NewElementDecoder, NewCoder, inferCoders, or a transform like TryCombinePerKey with a composite FullType kind not covered by inferCoder's switch — e.g. a custom typex kind registered by an extension, or a kind added in a newer Beam release while running an older coder.go.
Common situations: Upgrading Beam so pipeline data flows through a composite type the installed coder.go does not handle; custom DoFn/PCollection element types using exotic typex kinds; SDK/worker version skew.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- inferCoder: unknown container kind
- Unexpected type
- coder must not be nil
- err
- expected WV coder for user state
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/be592d855a3be0f5.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/coder.go:271
if err != nil {
return nil, err
}
switch t.Type() {
case typex.KVType:
return &coder.Coder{Kind: coder.KV, T: t, Components: c}, nil
case typex.CoGBKType:
return &coder.Coder{Kind: coder.CoGBK, T: t, Components: c}, nil
case typex.WindowedValueType:
// TODO(herohde) 4/15/2018: do we ever infer W types now that PCollections
// are non-windowed? We either need to know the windowing strategy or
// we should remove this case.
return &coder.Coder{Kind: coder.WindowedValue, T: t, Components: c, Window: coder.NewGlobalWindow()}, nil
case typex.ShardedKeyType:
return &coder.Coder{Kind: coder.ShardedKey, T: t, Components: c}, nil
default:
panic(fmt.Sprintf("Unexpected composite type: %v", t))
}
default:
panic(fmt.Sprintf("Unexpected type: %v", t))
}
}
func inferCoders(list []FullType) ([]*coder.Coder, error) {
var ret []*coder.Coder
for _, t := range list {
c, err := inferCoder(t)
if err != nil {
return nil, err
}
ret = append(ret, c)
}
return ret, nil
}
View on GitHub (pinned to 12126d8942)