{"record":{"id":"584dc74b24747e50","repo":"apache/beam","slug":"incompatible-func-type-got-func-v-with-v-inputs-and-v-584dc7","errorCode":null,"errorMessage":"Incompatible func type: got func %v with %v inputs and %v outputs, want 4 inputs and 4 outputs","messagePattern":"Incompatible func type: got func (.+?) with (.+?) inputs and (.+?) outputs, want 4 inputs and 4 outputs","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/util/reflectx/calls.go","lineNumber":1049,"sourceCode":"}\n\nfunc (c *shimFunc4x4) Type() reflect.Type {\n\treturn c.inner.Type()\n}\n\nfunc (c *shimFunc4x4) Call(args []any) []any {\n\treturn c.inner.Call(args)\n}\n\nfunc (c *shimFunc4x4) Call4x4(arg0, arg1, arg2, arg3 any) (any, any, any, any) {\n\tret := c.inner.Call([]any{arg0, arg1, arg2, arg3})\n\t_ = ret\n\treturn ret[0], ret[1], ret[2], ret[3]\n}\n\nfunc ToFunc4x4(c Func) Func4x4 {\n\tif c.Type().NumIn() != 4 || c.Type().NumOut() != 4 {\n\t\tpanic(fmt.Sprintf(\"Incompatible func type: got func %v with %v inputs and %v outputs, want 4 inputs and 4 outputs\", c.Type(), c.Type().NumIn(), c.Type().NumOut()))\n\t}\n\tif sc, ok := c.(Func4x4); ok {\n\t\treturn sc\n\t}\n\treturn &shimFunc4x4{inner: c}\n}\n\nfunc MakeFunc4x4(fn any) Func4x4 {\n\treturn ToFunc4x4(MakeFunc(fn))\n}\n\ntype Func5x0 interface {\n\tFunc\n\tCall5x0(any, any, any, any, any)\n}\n\ntype shimFunc5x0 struct {\n\tinner Func","sourceCodeStart":1031,"sourceCodeEnd":1067,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/util/reflectx/calls.go#L1031-L1067","documentation":"reflectx.ToFunc4x4 wraps a generic reflectx.Func into a fixed-arity Func4x4 (4 inputs, 4 outputs). Before wrapping it asserts the underlying func's reflect.Type has exactly 4 inputs and 4 outputs; otherwise it panics with this message. Apache Beam's DoFn machinery uses these shims to call user functions efficiently, so an arity mismatch means the registration signature does not match what the pipeline expects.","triggerScenarios":"Calling reflectx.ToFunc4x4(c) where c.Type().NumIn() != 4 or c.Type().NumOut() != 4. Typically reached via beam.ParDo/beam.TryParDo registering a function whose signature has 4 emit-consumable inputs but not exactly 4 return values (e.g. returning (T, E, bool) or nothing).","commonSituations":"DoFn.ProcessElement-style functions written with the wrong number of return values after a refactor; adding an error or element type to a return tuple without updating arity; passing a 4-in/2-out function where a 4x4 signature (e.g. with context and emit) is expected.","solutions":["Count the function's inputs and return values and adjust the signature to exactly 4 inputs and 4 outputs (adding named results or merging them as needed).","Use the ToFuncN x M variant that matches the actual signature (e.g. ToFunc4x2) instead of ToFunc4x4.","If using a DoFn struct, check that ProcessElement's parameter and return-list arity matches the fixed-arity registration being attempted."],"exampleFix":"// before\nfunc fn(a A, b B, c C, d D) (X, Y) { ... }\nreflectx.ToFunc4x4(fn) // panics: 2 outputs\n\n// after\nfunc fn(a A, b B, c C, d D) (W, X, Y, Z) { ... }\nreflectx.ToFunc4x4(fn)","handlingStrategy":"validation","validationCode":"fn := reflect.TypeOf(fnAny)\nif fn.Kind() == reflect.Func && fn.NumIn() == 4 && fn.NumOut() == 4 {\n    _ = reflectx.ToFunc4x4(fnAny)\n}","typeGuard":"func isFunc4x4(f interface{}) bool {\n    t := reflect.TypeOf(f)\n    return t != nil && t.Kind() == reflect.Func && t.NumIn() == 4 && t.NumOut() == 4\n}","tryCatchPattern":"func safeToFunc4x4(c reflectx.Func) (f reflectx.Func4x4, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"ToFunc4x4 failed: %v\", r)\n        }\n    }()\n    return reflectx.ToFunc4x4(c), nil\n}","preventionTips":["Count inputs and outputs of your DoFn function before choosing a ToFuncN x M wrapper.","Prefer DoFn structs with ProcessElement so Beam derives signatures automatically.","Add a unit test that calls the ToFunc helper for every registered function.","When changing a function's signature, grep for its registration site and update the arity helper."],"tags":["go","apache-beam","reflection","function-signature"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}