apache/beam · error
Type " " of kind " " not permitted in concrete types. All…
Error message
Type "%v" of kind "%v" not permitted in concrete types. All types must be serializable.
What it means
isConcrete rejects element types whose Go kind is unserializable: Chan or Func. Beam must serialize elements between bundles and across workers, and channels/functions cannot be encoded, so any concrete type graph containing them (exported, at any nesting depth) is rejected. Reached via IsConcrete/CheckConcrete when declaring DoFn or PCollection element types.
Solutions
- Remove chan/func fields from element types; unexport them if they are only runtime-local state.
- Replace callback fields with data (e.g. an enum/flag the worker interprets) and reconstruct behavior in the DoFn.
- For notification-style patterns, emit identifiers and resolve behavior on the consumer side.
- Call typex.CheckConcrete(reflect.TypeOf(myElem)) early in tests to catch offending nested fields.
Example fix
// before
type Event struct {
OnDone func()
}
// after
type Event struct {
DoneFlag bool
} Defensive patterns
Strategy: type-guard
Validate before calling
func serializable(t reflect.Type) error {
switch t.Kind() {
case reflect.Chan, reflect.Func:
return fmt.Errorf("unserializable kind %v in %v", t.Kind(), t)
}
return nil
} Type guard
func hasChanOrFunc(t reflect.Type) bool {
switch t.Kind() {
case reflect.Chan, reflect.Func:
return true
}
return false
} Prevention
- Never include chan or func fields in element types — export or not, they surface via exported wrappers.
- Replace callbacks with data-driven flags resolved inside DoFns.
- Validate element types with typex.CheckConcrete before pipeline construction.
When it happens
Trigger: A DoFn input/output type (or a nested exported field) that is a channel (chan int) or a function value (func() error); slices/maps of channels or funcs; embedding a callback field in a data struct.
Common situations: Passing callbacks through PCollections to 'configure downstream behavior'; structs with notifier channels for tests reused as element types; wrapping io.Reader/func() error in event records.
Related errors
- Nested type in struct
- Type " " of kind " " not permitted in concrete types. All…
- bad base type
- bad channel direction
- bad element type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/61f49aede974df84.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/typex/class.go:135
// Handle special types.
if t == nil ||
t == EventTimeType ||
t.Implements(WindowType) ||
t == PaneInfoType ||
t == TimersType ||
t == BundleFinalizationType ||
t == reflectx.Error ||
t == reflectx.Context ||
IsUniversal(t) {
return errors.Errorf("Special type \"%v\" not permitted in concrete types", t)
}
switch t.Kind() {
case reflect.Invalid, reflect.UnsafePointer, reflect.Uintptr:
return errors.Errorf("Type \"%v\" of kind \"%v\" not permitted in concrete types. All types must be manageable.", t, t.Kind()) // no unmanageable types
case reflect.Chan, reflect.Func:
return errors.Errorf("Type \"%v\" of kind \"%v\" not permitted in concrete types. All types must be serializable.", t, t.Kind()) // no unserializable types
case reflect.Map:
err := isConcrete(t.Elem(), visited)
if err == nil {
err = isConcrete(t.Key(), visited)
}
if err != nil {
err = errors.Wrapf(err, "Nested type in map \"%v\" not permitted in concrete types.", t)
}
return err
case reflect.Array, reflect.Slice, reflect.Ptr:
err := isConcrete(t.Elem(), visited)
if err != nil {
err = errors.Wrapf(err, "Nested type in %v \"%v\" not permitted in concrete types.", t.Kind(), t)
}
return err
View on GitHub (pinned to 12126d8942)