apache/beam · error

Special type " " not permitted in concrete types

Error message

Special type "%v" not permitted in concrete types

What it means

isConcrete validates that a Go type is allowed as a Beam element type. Types reserved for special pipeline semantics (PaneInfo, Timers, BundleFinalization, Error, Context, and universal types) are rejected as concrete element types because Beam handles them via their special universals, not as ordinary data. isConcrete is reached via IsConcrete/CheckConcrete when declaring PCollection element types.

Solutions

  1. Change the element type to a plain serializable Go type instead of error/context/special Beam types.
  2. If you intended polymorphism, use typex.T / typex.X universals in the DoFn signature, not as concrete PCollection types.
  3. Handle errors inside the DoFn (emit to a side output or drop/log them) rather than emitting error values.
  4. Use typex.CheckConcrete on your intended type during development to catch this early with a clear message.

Example fix

// before
beam.ParDo(s, func(ctx context.Context, e Event) (context.Context, error) { ... })

// after
beam.ParDo(s, func(ctx context.Context, e Event) Result { ... })
Defensive patterns

Strategy: validation

Validate before calling

if err := typex.CheckConcrete(reflect.TypeOf(elem)); err != nil {
    return fmt.Errorf("element type %T not usable: %w", elem, err)
}

Type guard

func isBeamElementType(t reflect.Type) bool {
    return t != nil && typex.IsConcrete(t)
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        err = fmt.Errorf("type validation failed: %v", r)
    }
}()

Prevention

When it happens

Trigger: Declaring a PCollection or DoFn output/input whose element type is reflectx.Error, reflectx.Context, typex.PaneInfoType, TimersType, BundleFinalizationType, or a universal (e.g. typex.New(reflectx.Error)) — e.g. beam.ParDo with a function emitting an error or context value.

Common situations: DoFn methods with signatures like ProcessElement(context.Context, ...) emitted as outputs by mistake; trying to emit error values down a PCollection; binding a universal type variable (T, X) as a concrete element type in tests.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

	// Check that we haven't hit a recursive loop.
	// If there's an invalid field in a recursive type
	// then the layer above will find it.
	if visited[t] {
		return nil
	}
	visited[t] = true

	// 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

View on GitHub (pinned to 12126d8942)