apache/beam · error
prism consistency error: trying to remove a timer for a key…
Error message
prism consistency error: trying to remove a timer for a key without timers: %v,%+v
What it means
timerHandler.removeTimer expects an entry in nextFiring for the given user key before deleting a timer. When no timer map exists for that key, prism's internal timer bookkeeping is inconsistent, so it panics with this consistency error. This indicates a runner-side bug or a malformed timer protocol interaction rather than user data corruption.
Solutions
- Update to the latest Beam version; this class of prism consistency panic is usually fixed in newer releases.
- Check for duplicate timer firings for the same key/timestamp in the pipeline (e.g. re-setting timers inside timers).
- Capture the job graph and file a bug with the Beam project including the pipeline and stage that panicked.
- As a workaround, avoid clearing timers from within the same bundle that fires them.
Defensive patterns
Strategy: try-catch
Validate before calling
// Before firing, verify the timer is registered
if _, ok := handler.HasTimer(userKey, timerKey); !ok {
log.Printf("timer %v for key %v not registered; skipping fire", timerKey, userKey)
} Try / catch
func safeFire(h *timerHandler, userKey string, key timerKey) (recovered any) {
defer func() { recovered = recover() }()
h.FireAt(userKey, key)
return nil
} Prevention
- Avoid setting and clearing the same timer within one bundle
- Upgrade Beam to get timer-handling fixes
- Report panics with a reproducing TestStream script
When it happens
Trigger: FireAt processing a firing request references a timer for a user key that was never registered in nextFiring, e.g. duplicate fire callbacks, timers cleared twice, or a test-stream replay referencing an already-removed timer.
Common situations: Running pipelines with timers on prism while retrying bundles, replaying TestStream contents, or hitting races between timer clearing and firing during job teardown.
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 non-existent…
- 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/9b14704a6be20dde.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/runners/prism/internal/engine/timers.go:325
return map[timerKey]fireElement{}
}},
}
}
// 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] = byKeysView on GitHub (pinned to 12126d8942)