apache/beam · error

panic(formatParDoError(dofn, len(ret), 3))

Error message

panic(formatParDoError(dofn, len(ret), 3))

What it means

ParDo3 applies a DoFn expected to produce exactly 3 outputs. If TryParDo returns a different number of PCollections (because the DoFn's ProcessElement signature does not emit exactly 3 values), the library panics with formatParDoError, a concise diagnostic naming the DoFn, the actual output count, and the expected count.

Source

Thrown at sdks/go/pkg/beam/pardo.go:451

	return ret[0]
}

// TODO(herohde) 6/1/2017: add windowing aspects to above documentation.

// ParDo2 inserts a ParDo with 2 outputs into the pipeline.
func ParDo2(s Scope, dofn any, col PCollection, opts ...Option) (PCollection, PCollection) {
	ret := MustN(TryParDo(s, dofn, col, opts...))
	if len(ret) != 2 {
		panic(formatParDoError(dofn, len(ret), 2))
	}
	return ret[0], ret[1]
}

// ParDo3 inserts a ParDo with 3 outputs into the pipeline.
func ParDo3(s Scope, dofn any, col PCollection, opts ...Option) (PCollection, PCollection, PCollection) {
	ret := MustN(TryParDo(s, dofn, col, opts...))
	if len(ret) != 3 {
		panic(formatParDoError(dofn, len(ret), 3))
	}
	return ret[0], ret[1], ret[2]
}

// ParDo4 inserts a ParDo with 4 outputs into the pipeline.
func ParDo4(s Scope, dofn any, col PCollection, opts ...Option) (PCollection, PCollection, PCollection, PCollection) {
	ret := MustN(TryParDo(s, dofn, col, opts...))
	if len(ret) != 4 {
		panic(formatParDoError(dofn, len(ret), 4))
	}
	return ret[0], ret[1], ret[2], ret[3]
}

// ParDo5 inserts a ParDo with 5 outputs into the pipeline.
func ParDo5(s Scope, dofn any, col PCollection, opts ...Option) (PCollection, PCollection, PCollection, PCollection, PCollection) {
	ret := MustN(TryParDo(s, dofn, col, opts...))
	if len(ret) != 5 {
		panic(formatParDoError(dofn, len(ret), 5))

View on GitHub (pinned to 12126d8942)

Solutions

  1. Check the DoFn's ProcessElement signature and make it emit exactly 3 outputs (3 emit fields or 3 return values).
  2. Or switch to the matching helper: use ParDo2/ParDo4/etc., or ParDoN/TryParDo for arbitrary output counts.
  3. Read the panic message from formatParDoError, which names the DoFn type, actual count, and expected count, to pinpoint the mismatch.

Example fix

// before: DoFn emits only 2 outputs but ParDo3 is used
func (f *splitFn) ProcessElement(kv beam.KV) (string, int) { ... }
beam.ParDo3(s, &splitFn{}, col)

// after: emit exactly 3 outputs
func (f *splitFn) ProcessElement(kv beam.KV) (string, string, int) { ... }
beam.ParDo3(s, &splitFn{}, col)
Defensive patterns

Strategy: validation

Validate before calling

// verify DoFn output count before choosing ParDo3
if outputsOfMyDoFn != 3 {
    log.Fatalf("DoFn must emit exactly 3 outputs, got %d", outputsOfMyDoFn)
}

Try / catch

// Go panics are not catchable by recover in another goroutine; wrap pipeline construction:
func buildPipeline() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("pardo construction failed: %v", r)
        }
    }()
    beam.ParDo3(s, &splitFn{}, col)
    return nil
}

Prevention

When it happens

Trigger: Calling beam.ParDo3 with a DoFn whose ProcessElement returns/emits fewer or more than 3 outputs (e.g. a DoFn with 2 emit parameters or return values).

Common situations: Refactoring a DoFn to add/remove an output without updating the ParDoN variant; copying a single-output DoFn into a multi-output pipeline; mismatching emit function count in the DoFn struct versus the chosen ParDoN helper.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/66dd03b9b249843d. Report an issue: GitHub.