apache/beam · error
prism consistency error: trying to remove a non-existent…
Error message
prism consistency error: trying to remove a non-existent timer for a key: %v,%+v
What it means
This is the second consistency check in timerHandler.removeTimer: the per-user-key timer map exists, but the specific timerKey being removed is absent. Prism's timer state expects every removal to correspond to a previously scheduled timer; a missing entry means firing and clearing bookkeeping got out of sync.
Solutions
- Upgrade Beam/prism to the latest version where timer deduplication fixes may apply.
- Ensure the pipeline does not clear the same timer twice or set a timer while clearing it in the same bundle.
- Log the userKey and timerKey at the failure and file a Beam bug with a reproducing pipeline or TestStream script.
Defensive patterns
Strategy: try-catch
Validate before calling
// Guard removal: only clear a timer if it still exists
if h.TimerExists(userKey, key) {
h.ClearTimer(userKey, key)
} Try / catch
func safeRemove(h *timerHandler, userKey string, key timerKey) (recovered any) {
defer func() { recovered = recover() }()
h.FireAt(userKey, key)
return nil
} Prevention
- Don't double-clear timers or clear timers from concurrent stages
- Match timer tags/timestamps exactly when setting and clearing
- Upgrade prism; timer dedup bugs are fixed over time
When it happens
Trigger: FireAt fires a timer whose entry was already deleted (double-fire or clear-then-fire race), or a timer key arrives with a mismatched tag/pane so it no longer matches the stored key.
Common situations: TestStream-driven tests replaying events out of order, pipelines setting and clearing timers concurrently across bundles, or prism version bugs in timer handling.
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
- prism consistency error: trying to remove a timer for a key…
- batch.groupIntoBatchesFn: unexpected timer family
- expected single value map, had
- panic(err) propagating lpUnknownCoders error
- unable to decode ParDoPayload for transform
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/02910bf7030b3792.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/runners/prism/internal/engine/timers.go:329
// timers returns the timers for the userkey.
func (th *timerHandler) timers(timer element) map[timerKey]fireElement {
timers, ok := th.nextFiring[string(timer.keyBytes)]
if !ok {
timers = th.firingMapPool.Get().(map[timerKey]fireElement)
th.nextFiring[string(timer.keyBytes)] = timers
}
return timers
}
func (th *timerHandler) removeTimer(userKey string, key timerKey) element {
timers, ok := th.nextFiring[userKey]
if !ok {
panic(fmt.Sprintf("prism consistency error: trying to remove a timer for a key without timers: %v,%+v", userKey, key))
}
times, ok := timers[key]
if !ok {
panic(fmt.Sprintf("prism consistency error: trying to remove a non-existent timer for a key: %v,%+v", userKey, key))
}
delete(timers, key)
if len(timers) == 0 {
delete(th.nextFiring, userKey)
th.firingMapPool.Put(timers)
}
return times.timer
}
func (th *timerHandler) add(key timerKey, newFire fireElement) {
byKeys, ok := th.toFire[newFire.firing]
if !ok {
byKeys = th.userKeysSetPool.Get().(map[string]set[timerKey])
th.toFire[newFire.firing] = byKeys
heap.Push(&th.order, newFire.firing) // We only need to add a firing order when inserting.
}
timers, ok := byKeys[string(newFire.timer.keyBytes)]
if !ok {View on GitHub (pinned to 12126d8942)