apache/beam · error

Type interface{} isn't a supported PCollection type

Error message

Type interface{} isn't a supported PCollection type

What it means

Apache Beam Go SDK rejects DoFn/emit function parameters (or return values reached via emit signatures) typed as plain `interface{}` (any), because Beam needs a concrete, coder-encodable PCollection element type. Unbounded `any` cannot be mapped to a Beam type descriptor or default coder. The check is skipped only for types marked as universal (typex.IsUniversal).

Source

Thrown at sdks/go/pkg/beam/core/funcx/output.go:88

		return nil, false, nil
	}

	var ret []reflect.Type
	skip := 0
	if t.In(0) == typex.EventTimeType {
		ret = append(ret, typex.EventTimeType)
		skip = 1
	}
	if t.NumIn()-skip > 2 || t.NumIn() == skip {
		return nil, false, nil
	}
	emptyInterface := reflect.TypeOf((*any)(nil)).Elem()
	for i := skip; i < t.NumIn(); i++ {
		if ok, err := isInParam(t.In(i)); !ok {
			return nil, false, errors.Wrap(err, errIllegalParametersInEmit)
		}
		if ((t.In(i).Kind() == reflect.Ptr && t.In(i).Elem() == emptyInterface) || t.In(i) == emptyInterface) && !typex.IsUniversal(t.In(i)) {
			return nil, false, errors.New("Type interface{} isn't a supported PCollection type")
		}
		ret = append(ret, t.In(i))
	}
	return ret, true, nil
}

func isInParam(t reflect.Type) (bool, error) {
	if typex.IsUniversal(t) || typex.IsContainer(t) {
		return true, nil
	}
	return typex.CheckConcrete(t)
}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Replace the `interface{}`/`any` parameter with a concrete element type (e.g. string, KV<string,int>) in the emit function signature.
  2. If generic behavior is truly intended, mark the type as universal via typex.IsUniversal-supported declarations (e.g. use typex.T or a universal type marker) instead of bare `any`.
  3. Use Beam generics helpers (beam.ParDo with typed DoFn structs) so signatures are inferred with concrete types.
  4. Check upstream callers of UnfoldEmit to see which signature is being rejected and fix the DoFn method definition.

Example fix

// before
func (fn *myFn) ProcessElement(e func(any), v string) {}
// after
func (fn *myFn) ProcessElement(e func(int), v string) {}
Defensive patterns

Strategy: validation

Validate before calling

func hasAnyEmitParam(fn reflect.Type) bool {
    anyT := reflect.TypeOf((*any)(nil)).Elem()
    for i := 0; i < fn.NumIn(); i++ {
        p := fn.In(i)
        if (p.Kind() == reflect.Ptr && p.Elem() == anyT) || p == anyT {
            return true
        }
    }
    return false
}

Type guard

func isConcrete(t reflect.Type) bool { return t != nil && t != reflect.TypeOf((*any)(nil)).Elem() }

Prevention

When it happens

Trigger: Defining a DoFn whose ProcessElement emits via a function passed to reflection-based unfolding (unfoldEmit, called from IsEmit/UnfoldEmit) where an input parameter is `any` or `*any` and not declared universal — e.g. `func(e Emitter<any>, v string)` or a callback parameter of type `interface{}`.

Common situations: Writing generic helpers over reflect.Type, migrating code from `interface{}` placeholders after refactoring, or hand-rolling emit signatures in custom combinators/transform builders instead of concrete element types.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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