{"record":{"id":"69d8e97fcb691468","repo":"apache/beam","slug":"panic-formatpardoerror-dofn-len-ret-4","errorCode":null,"errorMessage":"panic(formatParDoError(dofn, len(ret), 4))","messagePattern":"panic\\(formatParDoError\\(dofn, len\\(ret\\), 4\\)\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/pardo.go","lineNumber":460,"sourceCode":"\t\tpanic(formatParDoError(dofn, len(ret), 2))\n\t}\n\treturn ret[0], ret[1]\n}\n\n// ParDo3 inserts a ParDo with 3 outputs into the pipeline.\nfunc ParDo3(s Scope, dofn any, col PCollection, opts ...Option) (PCollection, PCollection, PCollection) {\n\tret := MustN(TryParDo(s, dofn, col, opts...))\n\tif len(ret) != 3 {\n\t\tpanic(formatParDoError(dofn, len(ret), 3))\n\t}\n\treturn ret[0], ret[1], ret[2]\n}\n\n// ParDo4 inserts a ParDo with 4 outputs into the pipeline.\nfunc ParDo4(s Scope, dofn any, col PCollection, opts ...Option) (PCollection, PCollection, PCollection, PCollection) {\n\tret := MustN(TryParDo(s, dofn, col, opts...))\n\tif len(ret) != 4 {\n\t\tpanic(formatParDoError(dofn, len(ret), 4))\n\t}\n\treturn ret[0], ret[1], ret[2], ret[3]\n}\n\n// ParDo5 inserts a ParDo with 5 outputs into the pipeline.\nfunc ParDo5(s Scope, dofn any, col PCollection, opts ...Option) (PCollection, PCollection, PCollection, PCollection, PCollection) {\n\tret := MustN(TryParDo(s, dofn, col, opts...))\n\tif len(ret) != 5 {\n\t\tpanic(formatParDoError(dofn, len(ret), 5))\n\t}\n\treturn ret[0], ret[1], ret[2], ret[3], ret[4]\n}\n\n// ParDo6 inserts a ParDo with 6 outputs into the pipeline.\nfunc ParDo6(s Scope, dofn any, col PCollection, opts ...Option) (PCollection, PCollection, PCollection, PCollection, PCollection, PCollection) {\n\tret := MustN(TryParDo(s, dofn, col, opts...))\n\tif len(ret) != 6 {\n\t\tpanic(formatParDoError(dofn, len(ret), 6))","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/pardo.go#L442-L478","documentation":"ParDo4 applies a DoFn expected to produce exactly 4 outputs. If TryParDo returns a count other than 4, the library panics via formatParDoError with the DoFn name, actual count, and expected count of 4.","triggerScenarios":"Calling beam.ParDo4 (directly or via CoGBK/ReshuffleKV paths) with a DoFn whose ProcessElement does not emit exactly 4 outputs.","commonSituations":"DoFn was originally single-output and was reused with ParDo4; an emit parameter was removed during refactor; confusion between main output plus tag outputs versus pure emit-based outputs.","solutions":["Make the DoFn's ProcessElement emit exactly 4 outputs (4 emit fields or 4 return values).","Or call the ParDoN variant that matches the DoFn's actual output count.","Use TryParDo to get an error instead of a panic when the output count is uncertain."],"exampleFix":"// before: 3-output DoFn used with ParDo4\nfunc (f *fn) ProcessElement(x int) (int, int, int) { ... }\nbeam.ParDo4(s, &fn{}, col)\n\n// after: add a fourth output\nfunc (f *fn) ProcessElement(x int) (int, int, int, int) { ... }\nbeam.ParDo4(s, &fn{}, col)","handlingStrategy":"validation","validationCode":"// confirm 4 outputs exist before ParDo4\nif outputsOfMyDoFn != 4 {\n    log.Fatalf(\"expected 4 outputs, got %d\", outputsOfMyDoFn)\n}","typeGuard":null,"tryCatchPattern":"defer func() { if r := recover(); r != nil { err = fmt.Errorf(\"ParDo4 failed: %v\", r) } }()","preventionTips":["Match ParDoN number to the DoFn's emit arity exactly","Prefer ParDoN/TryParDo when arity may change","Review panic text from formatParDoError: it names DoFn, actual, expected counts"],"tags":["go","apache-beam","pardo","panic","signature-mismatch"],"backgroundTag":"invalid-argument-value","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"}