apache/beam · error

Nested type in map " " not permitted in concrete types.

Error message

Nested type in map "%v" not permitted in concrete types.

What it means

When validating a map type, isConcrete recursively checks the map's element and key types. If either nested type is not concrete, the error is wrapped with 'Nested type in map ...' to point at the containing map. This is the contextual wrapper revealing which map type in your type graph contains the offending key/value.

Solutions

  1. Read the wrapped cause chain (errors.Unwrap) to find the leaf offending kind (chan, func, unsafe.Pointer, etc.).
  2. Replace the offending map key/value type with a serializable type.
  3. Unexport the offending field if it is internal runtime state and should be skipped by validation.
  4. Validate intermediate types with typex.CheckConcrete before assembling larger element types.

Example fix

// before
type State struct {
    Handlers map[string]func()
}

// after
type State struct {
    HandlerNames []string
}
Defensive patterns

Strategy: validation

Validate before calling

mv := reflect.TypeOf(myMapElem)
if err := typex.CheckConcrete(mv); err != nil {
    return fmt.Errorf("map element type rejected: %w", err)
}

Type guard

func mapValueSafe(t reflect.Type) bool {
    return t.Kind() == reflect.Map && typex.IsConcrete(t)
}

Prevention

When it happens

Trigger: Declaring element types like map[string]chan int, map[unsafe.Pointer]X, map[string]func(), or maps nested inside structs/slices where the value or key type fails isConcrete.

Common situations: Event structs with map[string]interface{} (interface may be fine, but nested chan/func values are not); lookup tables keyed or valued by pointers; JSON-decoded payloads holding func/channel fields.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/b01908cea25a64d3. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/core/typex/class.go:143

		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

	case reflect.Struct:
		for i := 0; i < t.NumField(); i++ {
			// We ignore private fields under the assumption that they are
			// either not needed or will be coded manually. For combiner
			// accumulators, we need types that need non-trivial coding. Also,
			// Go serialization schemes in general ignore private fields.

			f := t.Field(i)

View on GitHub (pinned to 12126d8942)