{"record":{"id":"23b85cc5cd1d696e","repo":"apache/beam","slug":"special-type-v-not-permitted-in-concrete-types","errorCode":null,"errorMessage":"Special type \"%v\" not permitted in concrete types","messagePattern":"Special type \"(.+?)\" not permitted in concrete types","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/typex/class.go","lineNumber":127,"sourceCode":"\t// Check that we haven't hit a recursive loop.\n\t// If there's an invalid field in a recursive type\n\t// then the layer above will find it.\n\tif visited[t] {\n\t\treturn nil\n\t}\n\tvisited[t] = true\n\n\t// Handle special types.\n\tif t == nil ||\n\t\tt == EventTimeType ||\n\t\tt.Implements(WindowType) ||\n\t\tt == PaneInfoType ||\n\t\tt == TimersType ||\n\t\tt == BundleFinalizationType ||\n\t\tt == reflectx.Error ||\n\t\tt == reflectx.Context ||\n\t\tIsUniversal(t) {\n\t\treturn errors.Errorf(\"Special type \\\"%v\\\" not permitted in concrete types\", t)\n\t}\n\n\tswitch t.Kind() {\n\tcase reflect.Invalid, reflect.UnsafePointer, reflect.Uintptr:\n\t\treturn errors.Errorf(\"Type \\\"%v\\\" of kind \\\"%v\\\" not permitted in concrete types. All types must be manageable.\", t, t.Kind()) // no unmanageable types\n\n\tcase reflect.Chan, reflect.Func:\n\t\treturn errors.Errorf(\"Type \\\"%v\\\" of kind \\\"%v\\\" not permitted in concrete types. All types must be serializable.\", t, t.Kind()) // no unserializable types\n\n\tcase reflect.Map:\n\t\terr := isConcrete(t.Elem(), visited)\n\t\tif err == nil {\n\t\t\terr = isConcrete(t.Key(), visited)\n\t\t}\n\t\tif err != nil {\n\t\t\terr = errors.Wrapf(err, \"Nested type in map \\\"%v\\\" not permitted in concrete types.\", t)\n\t\t}\n\t\treturn err","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/typex/class.go#L109-L145","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the element type to a plain serializable Go type instead of error/context/special Beam types.","If you intended polymorphism, use typex.T / typex.X universals in the DoFn signature, not as concrete PCollection types.","Handle errors inside the DoFn (emit to a side output or drop/log them) rather than emitting error values.","Use typex.CheckConcrete on your intended type during development to catch this early with a clear message."],"exampleFix":"// before\nbeam.ParDo(s, func(ctx context.Context, e Event) (context.Context, error) { ... })\n\n// after\nbeam.ParDo(s, func(ctx context.Context, e Event) Result { ... })","handlingStrategy":"validation","validationCode":"if err := typex.CheckConcrete(reflect.TypeOf(elem)); err != nil {\n    return fmt.Errorf(\"element type %T not usable: %w\", elem, err)\n}","typeGuard":"func isBeamElementType(t reflect.Type) bool {\n    return t != nil && typex.IsConcrete(t)\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        err = fmt.Errorf(\"type validation failed: %v\", r)\n    }\n}()","preventionTips":["Never emit error, context.Context, or Beam special types (PaneInfo, Timers) as element types.","Use typex.T/typex.X only as DoFn signature universals, not as concrete PCollection types.","Run a unit test with typex.CheckConcrete on all pipeline element types."],"tags":["go","apache-beam","type-system"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}