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
- Avoid custom windowing with user state when using prism (only interval windows supported here)
- Verify SDK and prism versions match so window encodings agree
- Inspect the wKey bytes in the panic for truncation/corruption
- 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
- Use only interval windows with user state on prism
- Keep SDK and prism versions aligned
- Avoid custom window coders in stateful pipelines until supported
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
- WindowedValue coder with more than 2 components: %s
- Invalid to nest WindowedValue
- KV coder with more than 2 components: %s
- ShardedKey coder must have only 1 component: %s
- Runner forgot to LP this Row Coder. %v
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/7b3849aa6a5e420d.
Report an issue: GitHub.