apache/beam · error

ProcessElement uses a StateProvider, but no State structs ar

Error message

ProcessElement uses a StateProvider, but no State structs are attached to the DoFn. Ensure that you are including the State structs you're using to read/writeglobal state as public uppercase member variables.

What it means

This validation error fires when ProcessElement takes a StateProvider but the DoFn struct has zero attached State structs. Beam requires stateful reads/writes to go through exported (uppercase) State struct fields embedded in the DoFn; if none exist, the StateProvider has nothing to operate on and the DoFn is misconfigured.

Source

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

					"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. "+
				"All stateful DoFns must take a key/value pair as an input.")
		}
		if len(ps) == 0 {
			err := errors.Errorf("ProcessElement uses a StateProvider, but noState structs are attached to the DoFn")
			return errors.SetTopLevelMsgf(err, "ProcessElement uses a StateProvider, but no State structs are "+
				"attached to the DoFn. Ensure that you are including the State structs you're using to read/write"+
				"global state as public uppercase member variables.")
		}
		stateKeys := make(map[string]state.PipelineState)
		for _, s := range ps {
			k := s.StateKey()
			if orig, ok := stateKeys[k]; ok {
				err := errors.Errorf("Duplicate state key %v", k)
				return errors.SetTopLevelMsgf(err, "Duplicate state key %v used by %v and %v. Ensure that state keys are"+
					"unique per DoFn", k, orig, s)
			}
			t := s.StateType()
			if t != state.TypeValue && t != state.TypeBag && t != state.TypeCombining && t != state.TypeSet && t != state.TypeMap && t != state.TypeOrderedList {
				err := errors.Errorf("Unrecognized state type %v for state %v", t, s)
				return errors.SetTopLevelMsgf(err, "Unrecognized state type %v for state %v. Currently the only supported state"+
					"types are state.Value, state.Combining, state.Bag, state.Set, state.Map, and state.OrderedList", t, s)
			}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Add exported State struct fields to the DoFn, e.g. seen state.Value[string, int] as an uppercase member variable.
  2. Rename existing state fields to start with an uppercase letter so reflection detects them.
  3. Remove the StateProvider parameter if no state is actually used.

Example fix

// before
type CountFn struct{}
func (fn *CountFn) ProcessElement(ctx context.Context, sp state.Provider, w beam.KV[string, int]) error { ... }
// after
type CountFn struct {
    Seen state.Value[string, int]
}
func (fn *CountFn) ProcessElement(ctx context.Context, sp state.Provider, w beam.KV[string, int]) error { ... }
Defensive patterns

Strategy: validation

Validate before calling

t := reflect.TypeOf(CountFn{})
stateFields := 0
for i := 0; i < t.NumField(); i++ {
    if t.Field(i).IsExported() && t.Field(i).Name[0] >= 'A' && strings.Contains(fmt.Sprint(t.Field(i).Type), "state.") {
        stateFields++
    }
}
if stateFields == 0 { log.Fatal("stateful DoFn has no exported State fields") }

Try / catch

if err := beam.Run(ctx, p); err != nil {
    if strings.Contains(err.Error(), "no State structs are attached") {
        log.Fatalf("add exported state.Value/state.Bag fields to %T: %v", dofn, err)
    }
    return err
}

Prevention

When it happens

Trigger: Adding a state.Provider parameter to ProcessElement without declaring any exported State fields (state.Value, state.Bag, etc.) on the DoFn struct, or declaring them unexported (lowercase) so Beam's reflection doesn't see them.

Common situations: Starting to convert a DoFn to stateful (added the provider but not the fields yet); defining state fields with lowercase names; forgetting to embed the State struct member.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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