{"record":{"id":"cd43ed275e82d281","repo":"apache/beam","slug":"invoker-v-has-5-return-values-which-is-not-permitted-fn","errorCode":null,"errorMessage":"invoker: %v has > 5 return values, which is not permitted","messagePattern":"invoker: (.+?) has > 5 return values, which is not permitted","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/exec/fn_arity.tmpl","lineNumber":65,"sourceCode":"\t\t\tret := n.fn.Fn.Call(n.args)\n\n\t\t\t// (5) Return direct output, if any. Input timestamp and windows are implicitly\n\t\t\t// propagated.\n\t\t\tswitch len(ret) {\n\t\t\tcase 0:\n\t\t\t\treturn nil, nil\n\t\t\tcase 1:\n\t\t\t\treturn n.ret1(pn, ws, ts, ret[0])\n\t\t\tcase 2:\n\t\t\t\treturn n.ret2(pn, ws, ts, ret[0], ret[1])\n\t\t\tcase 3:\n\t\t\t\treturn n.ret3(pn, ws, ts, ret[0], ret[1], ret[2])\n\t\t\tcase 4:\n\t\t\t\treturn n.ret4(pn, ws, ts, ret[0], ret[1], ret[2], ret[3])\n\t\t\tcase 5:\n\t\t\t\treturn n.ret5(pn, ws, ts, ret[0], ret[1], ret[2], ret[3], ret[4])\n\t\t\t}\n\t\t\tpanic(fmt.Sprintf(\"invoker: %v has > 5 return values, which is not permitted\", n.fn.Fn.Name()))\n\t\t} \n\t}\n}\n","sourceCodeStart":47,"sourceCodeEnd":69,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/exec/fn_arity.tmpl#L47-L69","documentation":"The Beam Go function invoker supports DoFns with at most 5 return values; the generated dispatch table (fn_arity.tmpl) only handles 1-5. When a user function returns 6 or more values, the invoker falls through the switch and panics. This is an arity-limit guard enforced at pipeline runtime when the DoFn is first invoked.","triggerScenarios":"Defining a DoFn ProcessElement (or other invocable function) that returns 6 or more values, then running a pipeline with that DoFn.","commonSituations":"Users attempting to return many values from a single ProcessElement instead of bundling them into a struct; auto-generated DoFns with large outputs.","solutions":["Bundle multiple outputs into a struct or slice and return a single value","Split the function into multiple DoFns, or use tags/emitters to emit multiple outputs instead of returning them","Rewrite the function to return at most 5 values (per the invoker arity limit)"],"exampleFix":"// before\nfunc (f *myFn) ProcessElement(ctx context.Context, el T) (A, B, C, D, E, F) { ... }\n\n// after\ntype results struct{ A A; B B; C C; D D; E E; F F }\nfunc (f *myFn) ProcessElement(ctx context.Context, el T) results { ... }","handlingStrategy":"validation","validationCode":"if t := reflect.TypeOf(fn.ProcessElement); t.NumOut() > 5 {\n    return fmt.Errorf(\"ProcessElement returns %d values; max 5\", t.NumOut())\n}","typeGuard":"func hasValidDoFnArity(fn interface{}) bool {\n    m := reflect.ValueOf(fn).MethodByName(\"ProcessElement\")\n    if !m.IsValid() { return false }\n    t := m.Type()\n    return t.NumOut() <= 5\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"DoFn invocation failed: %v\", r)\n    }\n}()","preventionTips":["Keep ProcessElement return counts at 5 or fewer","Use structs or tagged outputs (beam.Out) for multiple results","Lint DoFn signatures before running pipelines"],"tags":["go","apache-beam","dofn","arity","panic"],"backgroundTag":"unsupported-operation","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"}