apache/beam · error

ProcessElement doesn't use a StateProvider, but State struct

Error message

ProcessElement doesn't use a StateProvider, but State structs are attached to the DoFn: %v
Ensure that you are using the StateProvider to perform any reads or writesof pipeline state.

What it means

The inverse of the stateful misconfiguration: this error is thrown when a DoFn has State structs attached but ProcessElement does not declare a StateProvider parameter. Attached State fields are inert unless the method takes a state.Provider to read/write them, so Beam flags the DoFn as incorrectly configured.

Source

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

		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)
			}
			stateKeys[k] = s
		}
	} else {
		if len(ps) > 0 {
			err := errors.Errorf("ProcessElement doesn't use a StateProvider, but State structs are attached to "+
				"the DoFn: %v", ps)
			return errors.SetTopLevelMsgf(err, "ProcessElement doesn't use a StateProvider, but State structs are "+
				"attached to the DoFn: %v\nEnsure that you are using the StateProvider to perform any reads or writes"+
				"of pipeline state.", ps)
		}
	}

	return nil
}

func validateOnTimerFn(fn *DoFn) error {
	if _, ok := fn.methods[onTimerName]; !ok {
		err := errors.Errorf("OnTimer function not defined for DoFn: %v", fn.Name())
		return errors.SetTopLevelMsgf(err, "OnTimer function not defined for DoFn: %v. Ensure that OnTimer function is implemented for the DoFn.", fn.Name())
	}

	pipelineTimers, _ := fn.PipelineTimers()

View on GitHub (pinned to 12126d8942)

Solutions

  1. Add a state.Provider parameter to ProcessElement (and key the input as KV) and use it to read/write the State fields.
  2. Remove the unused State fields from the DoFn struct if state is no longer needed.
  3. Verify ProcessElement's signature includes state.Provider before any State fields are declared.

Example fix

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

Strategy: validation

Validate before calling

hasStateFields := numExportedStateFields(fn) > 0
hasProvider := signatureHasStateProvider(fn.ProcessElement)
if hasStateFields && !hasProvider {
    log.Fatal("DoFn declares State fields but ProcessElement takes no state.Provider")
}

Try / catch

if err := beam.Run(ctx, p); err != nil {
    if strings.Contains(err.Error(), "doesn't use a StateProvider, but State structs are attached") {
        log.Fatalf("wire state.Provider into ProcessElement or delete unused State fields: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: Declaring State fields on a DoFn (state.Value, state.Bag, etc.) while ProcessElement's signature lacks the state.Provider parameter, e.g. after removing the provider argument during a refactor while leaving the fields behind.

Common situations: Stripping state usage from a DoFn but forgetting to remove the fields; copying a stateful DoFn and removing the provider parameter; scaffolding state fields before wiring up the method.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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