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

  1. Update to the latest Beam version; this class of prism consistency panic is usually fixed in newer releases.
  2. Check for duplicate timer firings for the same key/timestamp in the pipeline (e.g. re-setting timers inside timers).
  3. Capture the job graph and file a bug with the Beam project including the pipeline and stage that panicked.
  4. 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

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


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] = byKeys

View on GitHub (pinned to 12126d8942)