apache/beam · error

error decoding append bag user state window key %v: %v

Error message

error decoding append bag user state window key %v: %v

What it means

prism converts stored user-state window keys back into window values via an IntervalWindow decoder (toWindow). An empty key means the global window; otherwise the bytes must decode as an interval window. Failure panics because state data written by the SDK cannot be interpreted.

Source

Thrown at sdks/go/pkg/beam/runners/prism/internal/engine/data.go:101

}

// WriteTimers adds timers to the associated transform handler.
func (d *TentativeData) WriteTimers(transformID, familyID string, timers []byte) {
	if d.timers == nil {
		d.timers = map[TimerKey][][]byte{}
	}
	link := TimerKey{Transform: transformID, Family: familyID}
	d.timers[link] = append(d.timers[link], timers)
}

func (d *TentativeData) toWindow(wKey []byte) typex.Window {
	if len(wKey) == 0 {
		return window.GlobalWindow{}
	}
	// TODO: Custom Window handling.
	w, err := exec.MakeWindowDecoder(coder.NewIntervalWindow()).DecodeSingle(bytes.NewBuffer(wKey))
	if err != nil {
		panic(fmt.Sprintf("error decoding append bag user state window key %v: %v", wKey, err))
	}
	return w
}

// GetBagState retrieves available state from the tentative bundle data.
// The stateID has the Transform and Local fields populated, for the Transform and UserStateID respectively.
func (d *TentativeData) GetBagState(stateID LinkID, wKey, uKey []byte) [][]byte {
	winMap := d.state[stateID]
	w := d.toWindow(wKey)
	data := winMap[w][string(uKey)]
	slog.Debug("State() Bag.Get", slog.Any("StateID", stateID), slog.Any("UserKey", uKey), slog.Any("Window", w), slog.Any("Data", data))
	return data.Bag
}

func (d *TentativeData) appendState(stateID LinkID, wKey []byte) map[string]StateData {
	if d.state == nil {
		d.state = map[LinkID]map[typex.Window]map[string]StateData{}
	}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Avoid custom windowing with user state when using prism (only interval windows supported here)
  2. Verify SDK and prism versions match so window encodings agree
  3. Inspect the wKey bytes in the panic for truncation/corruption
  4. Report the failing pipeline to Beam if a custom window coder should be supported
Defensive patterns

Strategy: validation

Validate before calling

if len(wKey) == 0 { return window.GlobalWindow{} } // caller can pre-check before invoking state APIs
// and only use interval windows with prism user state

Try / catch

// toWindow panics; recover only at the state-handling boundary if wrapping prism
defer func() { if r := recover(); r != nil { log.Errorf("state window key decode failed: %v", r) } }()

Prevention

When it happens

Trigger: toWindow receives a non-empty wKey byte slice that exec.MakeWindowDecoder(coder.NewIntervalWindow()).DecodeSingle fails on — truncated, corrupt, or non-interval-window encoded bytes in the state key.

Common situations: SDK writes custom windows while prism assumes interval windows (see TODO in code); state key corruption; version skew in window encoding between SDK and prism.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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