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

  1. Remove chan/func fields from element types; unexport them if they are only runtime-local state.
  2. Replace callback fields with data (e.g. an enum/flag the worker interprets) and reconstruct behavior in the DoFn.
  3. For notification-style patterns, emit identifiers and resolve behavior on the consumer side.
  4. 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

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


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)