{"record":{"id":"39167fbde94398c2","repo":"apache/beam","slug":"processelement-uses-a-stateprovider-but-no-state-structs-are","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/fn.go","lineNumber":1357,"sourceCode":"\t\t\t\t\t\"Ensure that all watermark estimators in an SDF are the same type.\",\n\t\t\t\t\twatermarkEstimatorStateName, 0, method.Ret[0].T, watermarkStateT, watermarkEstimatorStateName)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc validateState(fn *DoFn, numIn mainInputs) error {\n\tps := fn.PipelineState()\n\n\tif _, hasSp := fn.methods[processElementName].StateProvider(); hasSp {\n\t\tif numIn == MainSingle {\n\t\t\terr := errors.Errorf(\"ProcessElement uses a StateProvider, but is not keyed\")\n\t\t\treturn errors.SetTopLevelMsgf(err, \"ProcessElement uses a StateProvider, but is not keyed. \"+\n\t\t\t\t\"All stateful DoFns must take a key/value pair as an input.\")\n\t\t}\n\t\tif len(ps) == 0 {\n\t\t\terr := errors.Errorf(\"ProcessElement uses a StateProvider, but noState structs are attached to the DoFn\")\n\t\t\treturn errors.SetTopLevelMsgf(err, \"ProcessElement uses a StateProvider, but no State structs are \"+\n\t\t\t\t\"attached to the DoFn. Ensure that you are including the State structs you're using to read/write\"+\n\t\t\t\t\"global state as public uppercase member variables.\")\n\t\t}\n\t\tstateKeys := make(map[string]state.PipelineState)\n\t\tfor _, s := range ps {\n\t\t\tk := s.StateKey()\n\t\t\tif orig, ok := stateKeys[k]; ok {\n\t\t\t\terr := errors.Errorf(\"Duplicate state key %v\", k)\n\t\t\t\treturn errors.SetTopLevelMsgf(err, \"Duplicate state key %v used by %v and %v. Ensure that state keys are\"+\n\t\t\t\t\t\"unique per DoFn\", k, orig, s)\n\t\t\t}\n\t\t\tt := s.StateType()\n\t\t\tif t != state.TypeValue && t != state.TypeBag && t != state.TypeCombining && t != state.TypeSet && t != state.TypeMap && t != state.TypeOrderedList {\n\t\t\t\terr := errors.Errorf(\"Unrecognized state type %v for state %v\", t, s)\n\t\t\t\treturn errors.SetTopLevelMsgf(err, \"Unrecognized state type %v for state %v. Currently the only supported state\"+\n\t\t\t\t\t\"types are state.Value, state.Combining, state.Bag, state.Set, state.Map, and state.OrderedList\", t, s)\n\t\t\t}","sourceCodeStart":1339,"sourceCodeEnd":1375,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/fn.go#L1339-L1375","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add exported State struct fields to the DoFn, e.g. seen state.Value[string, int] as an uppercase member variable.","Rename existing state fields to start with an uppercase letter so reflection detects them.","Remove the StateProvider parameter if no state is actually used."],"exampleFix":"// before\ntype CountFn struct{}\nfunc (fn *CountFn) ProcessElement(ctx context.Context, sp state.Provider, w beam.KV[string, int]) error { ... }\n// after\ntype CountFn struct {\n    Seen state.Value[string, int]\n}\nfunc (fn *CountFn) ProcessElement(ctx context.Context, sp state.Provider, w beam.KV[string, int]) error { ... }","handlingStrategy":"validation","validationCode":"t := reflect.TypeOf(CountFn{})\nstateFields := 0\nfor i := 0; i < t.NumField(); i++ {\n    if t.Field(i).IsExported() && t.Field(i).Name[0] >= 'A' && strings.Contains(fmt.Sprint(t.Field(i).Type), \"state.\") {\n        stateFields++\n    }\n}\nif stateFields == 0 { log.Fatal(\"stateful DoFn has no exported State fields\") }","typeGuard":null,"tryCatchPattern":"if err := beam.Run(ctx, p); err != nil {\n    if strings.Contains(err.Error(), \"no State structs are attached\") {\n        log.Fatalf(\"add exported state.Value/state.Bag fields to %T: %v\", dofn, err)\n    }\n    return err\n}","preventionTips":["Declare state fields as exported (uppercase) members directly on the DoFn struct","Never add a state.Provider parameter without also declaring the State fields you will use","Review DoFn struct definitions in code review when introducing state"],"tags":["go","apache-beam","dofn","state","reflection"],"backgroundTag":"missing-required-config-field","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"}