{"record":{"id":"29bb53c119f42fd6","repo":"apache/beam","slug":"optional-generic-parameter-not-bound-v","errorCode":null,"errorMessage":"optional generic parameter not bound %v","messagePattern":"optional generic parameter not bound (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/funcx/signature.go","lineNumber":214,"sourceCode":"}\n\n// TypeMismatchError indicates we didn't get the type we expected.\ntype TypeMismatchError struct {\n\tGot, Want reflect.Type\n}\n\nfunc (e *TypeMismatchError) Error() string {\n\treturn fmt.Sprintf(\"type mismatch: got %v, want %v\", e.Got, e.Want)\n}\n\nfunc matchOpt(list, models []reflect.Type, m map[string]reflect.Type) error {\n\ti := 0\n\tfor _, t := range list {\n\t\tif typex.IsUniversal(t) {\n\t\t\t// Substitute optional types, if bound.\n\t\t\tsubst, ok := m[t.Name()]\n\t\t\tif !ok {\n\t\t\t\treturn errors.Errorf(\"optional generic parameter not bound %v\", t.Name())\n\t\t\t}\n\t\t\tt = subst\n\t\t}\n\t\tfor i < len(models) && models[i] != t {\n\t\t\ti++\n\t\t}\n\n\t\tif i == len(models) {\n\t\t\treturn errors.Errorf(\"failed to match optional parameter %v\", t)\n\t\t}\n\t}\n\treturn nil\n}\n\n// MustSatisfy panics if the given fn does not satisfy the signature.\nfunc MustSatisfy(fn any, sig *Signature) {\n\tif err := Satisfy(fn, sig); err != nil {\n\t\tpanic(errors.Wrapf(err, \"fn does not satisfy signature %v\", sig))","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/funcx/signature.go#L196-L232","documentation":"matchOpt in signature.go matches a function's optional parameters against the signature's optional model list. If an optional parameter is a universal (generic) type that was never bound in the substitution map (because no required parameter pinned it to a concrete type), the optional generic cannot be substituted and this error is returned.","triggerScenarios":"Calling Satisfy where a function's optional argument/return is a generic type (e.g. X) but no required parameter or return of the signature binds X to a concrete type, so map lookup m[X] fails.","commonSituations":"Signatures where only the optional (emitter/iter) positions use a generic; writing a DoFn with an optional emit func(X) but no required input of type X; misuse of typex.NewVariable/Universal types in custom signatures.","solutions":["Add a required parameter or return of the generic type so it gets bound during generic binding.","Replace the generic in the optional position with a concrete type.","Reorder the function's parameters so the generic-typed one is required rather than optional."],"exampleFix":"// before\nsig := funcx.NewSignature(funcx.Args(typex.NewVariable(\"X\")), funcx.OptArgs(typex.Fn(func(typex.T) bool))) // X never bound\n// after\nsig := funcx.NewSignature(funcx.Args(typex.NewVariable(\"X\")), funcx.OptArgs(typex.Fn(func(typex.Event) bool))) // concrete optional","handlingStrategy":"validation","validationCode":"for _, opt := range sig.OptArgs {\n    if n := typex.UniversalName(opt); n != \"\" {\n        if _, bound := subst[n]; !bound {\n            return fmt.Errorf(\"generic %s used only in optional positions; add a required binding\", n)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always bind generics through at least one required parameter or return.","Avoid using universal types exclusively in optional/emitter positions.","Prefer concrete types in optional parameters of custom signatures."],"tags":["go","beam","generics","type-binding"],"backgroundTag":"missing-required-argument","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"}