{"record":{"id":"528ea15778e2396c","repo":"apache/beam","slug":"type-v-of-kind-v-not-allowed-must-be-ptr-type","errorCode":null,"errorMessage":"Type %v of kind %v not allowed, must be ptr type","messagePattern":"Type (.+?) of kind (.+?) not allowed, must be ptr type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/funcx/sideinput.go","lineNumber":104,"sourceCode":"\tif t.NumIn()-skip > 2 || t.NumIn() == skip {\n\t\treturn nil, false, nil\n\t}\n\n\tfor i := skip; i < t.NumIn(); i++ {\n\t\tif ok, err := isOutParam(t.In(i)); !ok {\n\t\t\treturn nil, false, errors.Wrap(err, errIllegalParametersInIter)\n\t\t}\n\t\tif reflect.TypeOf((*any)(nil)).Elem() == t.In(i).Elem() && !typex.IsUniversal(t.In(i)) {\n\t\t\treturn nil, false, errors.New(\"Type interface{} isn't a supported PCollection type\")\n\t\t}\n\t\tret = append(ret, t.In(i).Elem())\n\t}\n\treturn ret, true, nil\n}\n\nfunc isOutParam(t reflect.Type) (bool, error) {\n\tif t.Kind() != reflect.Ptr {\n\t\treturn false, errors.Errorf(\"Type %v of kind %v not allowed, must be ptr type\", t, t.Kind())\n\t}\n\tif typex.IsUniversal(t.Elem()) || typex.IsContainer(t.Elem()) {\n\t\treturn true, nil\n\t}\n\treturn typex.CheckConcrete(t.Elem())\n}\n\n// IsReIter returns true iff the supplied type is a functional iterator generator.\n//\n// A functional iterator generator is a parameter-less function that returns\n// single sweep functional iterators.\nfunc IsReIter(t reflect.Type) bool {\n\t_, ok := UnfoldReIter(t)\n\treturn ok\n}\n\n// IsMalformedReIter returns true iff the supplied type is an illegal functional\n// iterator generator and an error explaining why it is illegal. An iterator generator","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/funcx/sideinput.go#L86-L122","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Add the pointer: change `func(words []string)` to `func(words *[]string)`, `func(n int)` to `func(n *int)`.","Ensure the pointed-to element type is a valid PCollection type: typex.IsUniversal, typex.IsContainer, or passes typex.CheckConcrete.","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."],"exampleFix":"// before\nfn := func(words []string) bool { for _, w := range words { ... }; return true }\n// after\nfn := func(words *[]string) bool { for _, w := range *words { ... }; return true }","handlingStrategy":"validation","validationCode":"func paramsArePointers(fn interface{}) error {\n\tt := reflect.TypeOf(fn)\n\tif t == nil || t.Kind() != reflect.Func {\n\t\treturn fmt.Errorf(\"not a func: %T\", fn)\n\t}\n\tfor i := 0; i < t.NumIn(); i++ {\n\t\tif t.In(i).Kind() != reflect.Ptr {\n\t\t\treturn fmt.Errorf(\"param %d (%v) must be a pointer\", i, t.In(i))\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":"func isPtrParam(t reflect.Type) bool { return t != nil && t.Kind() == reflect.Ptr }","tryCatchPattern":"if ok, err := fx.IsIter(fn); !ok || err != nil {\n\tif err != nil && strings.Contains(err.Error(), \"must be ptr type\") {\n\t\treturn fmt.Errorf(\"fix side-input params to pointers: %w\", err)\n\t}\n}","preventionTips":["Mentally map each side input to `*T` where T is the PCollection element type.","Let the compiler/IDE flag value params before running the pipeline; run signature unit tests early.","Never write `func(v T)` for a side input; write `func(v *T)`.","When copying examples, double-check that asterisks were not lost in transcription."],"tags":["go","beam","side-input","pointer-type","reflection"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}