apache/beam · error

Type %v of kind %v not allowed, must be ptr type

Error message

Type %v of kind %v not allowed, must be ptr type

What it means

isOutParam in sdks/go/pkg/beam/core/funcx/sideinput.go requires every iterator side-input parameter to have reflect.Kind Ptr. If the parameter's kind is not a pointer, it returns a formatted error naming the type and its actual kind. The library throws it because iterator side inputs are materialized by writing into caller-provided storage, which in Go requires a pointer to the element type.

Source

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

	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.
//
// A functional iterator generator is a parameter-less function that returns
// single sweep functional iterators.
func IsReIter(t reflect.Type) bool {
	_, ok := UnfoldReIter(t)
	return ok
}

// IsMalformedReIter returns true iff the supplied type is an illegal functional
// iterator generator and an error explaining why it is illegal. An iterator generator

View on GitHub (pinned to 12126d8942)

Solutions

  1. Add the pointer: change `func(words []string)` to `func(words *[]string)`, `func(n int)` to `func(n *int)`.
  2. Ensure the pointed-to element type is a valid PCollection type: typex.IsUniversal, typex.IsContainer, or passes typex.CheckConcrete.
  3. If you intended a keyed iterator or reiterator, use the matching unfold (UnfoldMultiMap / UnfoldReIter) with the correct signature shape instead of forcing this parameter shape.

Example fix

// before
fn := func(words []string) bool { for _, w := range words { ... }; return true }
// after
fn := func(words *[]string) bool { for _, w := range *words { ... }; return true }
Defensive patterns

Strategy: validation

Validate before calling

func paramsArePointers(fn interface{}) error {
	t := reflect.TypeOf(fn)
	if t == nil || t.Kind() != reflect.Func {
		return fmt.Errorf("not a func: %T", fn)
	}
	for i := 0; i < t.NumIn(); i++ {
		if t.In(i).Kind() != reflect.Ptr {
			return fmt.Errorf("param %d (%v) must be a pointer", i, t.In(i))
		}
	}
	return nil
}

Type guard

func isPtrParam(t reflect.Type) bool { return t != nil && t.Kind() == reflect.Ptr }

Try / catch

if ok, err := fx.IsIter(fn); !ok || err != nil {
	if err != nil && strings.Contains(err.Error(), "must be ptr type") {
		return fmt.Errorf("fix side-input params to pointers: %w", err)
	}
}

Prevention

When it happens

Trigger: Passing a function whose side-input parameter is a value, slice value, struct, map, or interface (not a pointer) to fx.UnfoldIter / a DoFn side input, e.g. `func(words []string) bool` (kind Slice) or `func(n int) bool` (kind Int).

Common situations: Declaring a side input as a plain value type out of habit; using a named non-pointer struct type; forgetting the `*` after an IDE auto-complete; translating examples where the pointer was elided.

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/528ea15778e2396c. Report an issue: GitHub.