apache/beam · error

mismatched output type in method

Error message

mismatched output type in method %v, return value at index %v got: %v, want: %v (from method %v). Ensure that all watermark estimators in an SDF are the same type.

What it means

Beam Go validates that every watermark estimator method in a SplittableDoFn returns the same watermark state type. This error fires when a method's single return value's type differs from the watermark state type returned by the other estimator methods (e.g. a different WatermarkEstimator implementation's state type). Beam requires uniformity so state can be serialized and propagated consistently across bundles.

Solutions

  1. Make all watermark estimator methods in the SDF return the same watermark state type.
  2. Pick one WatermarkEstimator implementation and use its state type consistently across all methods.
  3. Search the DoFn for all methods taking/returning watermark state and align their types.

Example fix

// before
func (fn *MySDF) InitialWatermarkEstimatorState(et beam.EventTime, rt types.Type) watermark.ManualState { ... }
func (fn *MySDF) CreateWatermarkEstimatorState(s watermark.ManualState) watermark.State { ... }
// after
func (fn *MySDF) InitialWatermarkEstimatorState(et beam.EventTime, rt types.Type) watermark.State { ... }
func (fn *MySDF) CreateWatermarkEstimatorState(s watermark.State) watermark.State { ... }
Defensive patterns

Strategy: validation

Validate before calling

// ensure all watermark state types agree
if reflect.TypeOf(initialRet) != reflect.TypeOf(createRet) {
    return fmt.Errorf("watermark state types differ")
}

Type guard

func sameStateType(a, b watermark.State) bool { return reflect.TypeOf(a) == reflect.TypeOf(b) }

Try / catch

if err := beam.Run(ctx, ...); err != nil {
    if strings.Contains(err.Error(), "mismatched output type") {
        log.Fatalf("SDF watermark estimator methods must share one state type: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: An SDF has multiple watermark-estimator-related methods (e.g. InitialWatermarkEstimatorState and CreateWatermarkEstimatorState) whose return types differ, such as one returning watermark.ManualState and another watermark.State.

Common situations: Mixing estimator implementations in one SDF; refactoring one method to a different state type without updating the other; copying methods from two different SDF examples.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/graph/fn.go:1335

					watermarkEstimatorStateName, len(method.Param), 1, watermarkEstimatorStateName, processElementName)
			}
			if method.Param[0].T != watermarkEstimatorT {
				err := errors.Errorf("mismatched watermark state type in method %v, return %v. got: %v, want: %v",
					watermarkEstimatorStateName, 0, method.Param[0].T, watermarkEstimatorT)
				return errors.SetTopLevelMsgf(err, "mismatched watermark state type in method %v, "+
					"return value at index %v got: %v, want: %v (from method %v). "+
					"Ensure that all watermark states in an SDF are the same type.",
					watermarkEstimatorStateName, 0, method.Param[0].T, watermarkEstimatorT, watermarkEstimatorStateName)
			}
			if len(method.Ret) != 1 {
				err := errors.Errorf("unexpected number of elements returned in method %v. got: %v, want %v",
					watermarkEstimatorStateName, len(method.Ret), 1)
				return errors.SetTopLevelMsgf(err, "unexpected number of elements returned in method %v. "+
					"got: %v, want %v. Check that the signature conforms to the expected signature for %v.",
					watermarkEstimatorStateName, len(method.Ret), 1, watermarkEstimatorStateName)
			}
			if method.Ret[0].T != watermarkStateT {
				err := errors.Errorf("mismatched output type in method %v, return %v. got: %v, want: %v",
					watermarkEstimatorStateName, 0, method.Ret[0].T, watermarkStateT)
				return errors.SetTopLevelMsgf(err, "mismatched output type in method %v, "+
					"return value at index %v got: %v, want: %v (from method %v). "+
					"Ensure that all watermark estimators in an SDF are the same type.",
					watermarkEstimatorStateName, 0, method.Ret[0].T, watermarkStateT, watermarkEstimatorStateName)
			}
		}
	}
	return nil
}

func validateState(fn *DoFn, numIn mainInputs) error {
	ps := fn.PipelineState()

	if _, hasSp := fn.methods[processElementName].StateProvider(); hasSp {
		if numIn == MainSingle {
			err := errors.Errorf("ProcessElement uses a StateProvider, but is not keyed")
			return errors.SetTopLevelMsgf(err, "ProcessElement uses a StateProvider, but is not keyed. "+

View on GitHub (pinned to 12126d8942)