apache/beam · error

Type interface{} isn't a supported PCollection type

Error message

Type interface{} isn't a supported PCollection type

What it means

Like error 4410 but for side-input iterator/map parameters: unfoldIter in sideinput.go rejects iterator function signatures whose element type (the `In(i)` pointer's Elem) is `interface{}`/`any` and not universal. Beam requires concrete coder-encodable element types for side inputs.

Source

Thrown at sdks/go/pkg/beam/core/funcx/sideinput.go:95

	if t.NumIn() == 0 {
		return nil, false, nil
	}

	var ret []reflect.Type
	skip := 0
	if t.In(0).Kind() == reflect.Ptr && t.In(0).Elem() == typex.EventTimeType {
		return nil, false, errors.New(errIllegalEventTimeInIter)
	}
	if t.NumIn()-skip > 2 || t.NumIn() == skip {
		return nil, false, nil
	}

	for i := skip; i < t.NumIn(); i++ {
		if ok, err := isOutParam(t.In(i)); !ok {
			return nil, false, errors.Wrap(err, errIllegalParametersInIter)
		}
		if reflect.TypeOf((*any)(nil)).Elem() == t.In(i).Elem() && !typex.IsUniversal(t.In(i)) {
			return nil, false, errors.New("Type interface{} isn't a supported PCollection type")
		}
		ret = append(ret, t.In(i).Elem())
	}
	return ret, true, nil
}

func isOutParam(t reflect.Type) (bool, error) {
	if t.Kind() != reflect.Ptr {
		return false, errors.Errorf("Type %v of kind %v not allowed, must be ptr type", t, t.Kind())
	}
	if typex.IsUniversal(t.Elem()) || typex.IsContainer(t.Elem()) {
		return true, nil
	}
	return typex.CheckConcrete(t.Elem())
}

// IsReIter returns true iff the supplied type is a functional iterator generator.
//

View on GitHub (pinned to 12126d8942)

Solutions

  1. Change the iterator element type from `any` to the concrete PCollection element type.
  2. Use a universal type annotation (typex.IsUniversal-recognized) if genuinely type-erased behavior is needed.
  3. Let Beam infer side input types from the concrete PCollection instead of hand-writing `any` signatures.
  4. Review the DoFn method signature at the failing unfoldIter call site and tighten its types.

Example fix

// before
func (fn *f) ProcessElement(w string, i *func(any) bool) {}
// after
func (fn *f) ProcessElement(w string, i *func(int) bool) {}
Defensive patterns

Strategy: validation

Validate before calling

func sideIterElemIsAny(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().Kind() == reflect.Func && p.Elem().NumIn() > 0 && p.Elem().In(0) == anyT {
            return true
        }
    }
    return false
}

Type guard

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

Prevention

When it happens

Trigger: Declaring a side input iterator like `func(iter *func(v any) bool)` or a multi-map side input whose value type is `any` without a universal type annotation, when the DoFn is validated via IsIter/UnfoldIter.

Common situations: Generic container refactors that replaced concrete types with `any`, or writing helper functions accepting `interface{}` iterators for side inputs in custom pipeline utilities.

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/36445b314b06efa8. Report an issue: GitHub.