apache/beam · error

set or map state type

Error message

set or map state type %v must have a key coder type, none detected

What it means

A map or set user state (state.TypeMap / state.TypeSet) requires an associated key coder, registered under UserStateKeyCoderID. When translating the DoFn's state specs the marshaller found no key coder for this state, which is mandatory for keyed state types, so it returns this error naming the provider state.

Solutions

  1. Declare map/set state with the proper key type so the key coder is derived (state.MapState[K,V] / state.SetState[K])
  2. Verify the state's KeyCoder is registered via UserStateKeyCoderID in your provider
  3. Update the SDK if relying on automatic key-coder inference
  4. Replace map state with repeated value state + GBK if key coders cannot be provided

Example fix

// before
var st = state.MapState[...] // missing key coder
// after
type fn struct { counts state.MapState[string, int64] } // key type string derives coder
Defensive patterns

Strategy: validation

Validate before calling

// At pipeline construction, assert every map/set state declares a key coder
type keyed interface { StateType() state.Type; KeyCoder() Coder }
if st.StateType() == state.TypeMap || st.StateType() == state.TypeSet {
    if st.(keyed).KeyCoder() == nil { return errors.New("map/set state missing key coder") }
}

Type guard

func hasKeyCoder(ps state.ProviderSpec) bool {
    return ps.StateType() != state.TypeMap && ps.StateType() != state.TypeSet || ps.Has(UserStateKeyCoderID(ps))
}

Try / catch

if _, err := graphx.Marshal(p); err != nil {
    if strings.Contains(err.Error(), "must have a key coder type") {
        return fmt.Errorf("stateful DoFn misconfigured: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: Using state.MapState or state.SetState inside a DoFn without providing the key coder — e.g. declaring the state with a value type but no key type, or the state provider missing its key coder registration.

Common situations: Typo or wrong generic parameters when declaring map/set state; Beam SDK versions where key coder inference for map/set state changed; hand-rolled state providers in custom runners.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/translate.go:525

			m.requirements[URNRequiresStatefulProcessing] = true
			stateSpecs := make(map[string]*pipepb.StateSpec)
			for _, ps := range edge.Edge.DoFn.PipelineState() {
				coderID := ""
				c, ok := edge.Edge.StateCoders[UserStateCoderID(ps)]
				if ok {
					coderID, err = m.coders.Add(c)
					if err != nil {
						return handleErr(err)
					}
				}
				keyCoderID := ""
				if c, ok := edge.Edge.StateCoders[UserStateKeyCoderID(ps)]; ok {
					keyCoderID, err = m.coders.Add(c)
					if err != nil {
						return handleErr(err)
					}
				} else if ps.StateType() == state.TypeMap || ps.StateType() == state.TypeSet {
					return nil, errors.Errorf("set or map state type %v must have a key coder type, none detected", ps)
				}
				switch ps.StateType() {
				case state.TypeValue:
					stateSpecs[ps.StateKey()] = &pipepb.StateSpec{
						Spec: &pipepb.StateSpec_ReadModifyWriteSpec{
							ReadModifyWriteSpec: &pipepb.ReadModifyWriteStateSpec{
								CoderId: coderID,
							},
						},
						Protocol: &pipepb.FunctionSpec{
							Urn: URNBagUserState,
						},
					}
				case state.TypeBag:
					stateSpecs[ps.StateKey()] = &pipepb.StateSpec{
						Spec: &pipepb.StateSpec_BagSpec{
							BagSpec: &pipepb.BagStateSpec{
								ElementCoderId: coderID,

View on GitHub (pinned to 12126d8942)