{"record":{"id":"02910bf7030b3792","repo":"apache/beam","slug":"prism-consistency-error-trying-to-remove-a-non-existent","errorCode":null,"errorMessage":"prism consistency error: trying to remove a non-existent timer for a key: %v,%+v","messagePattern":"prism consistency error: trying to remove a non-existent timer for a key: (.+?),%\\+v","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/runners/prism/internal/engine/timers.go","lineNumber":329,"sourceCode":"\n// timers returns the timers for the userkey.\nfunc (th *timerHandler) timers(timer element) map[timerKey]fireElement {\n\ttimers, ok := th.nextFiring[string(timer.keyBytes)]\n\tif !ok {\n\t\ttimers = th.firingMapPool.Get().(map[timerKey]fireElement)\n\t\tth.nextFiring[string(timer.keyBytes)] = timers\n\t}\n\treturn timers\n}\n\nfunc (th *timerHandler) removeTimer(userKey string, key timerKey) element {\n\ttimers, ok := th.nextFiring[userKey]\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"prism consistency error: trying to remove a timer for a key without timers: %v,%+v\", userKey, key))\n\t}\n\ttimes, ok := timers[key]\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"prism consistency error: trying to remove a non-existent timer for a key: %v,%+v\", userKey, key))\n\t}\n\tdelete(timers, key)\n\tif len(timers) == 0 {\n\t\tdelete(th.nextFiring, userKey)\n\t\tth.firingMapPool.Put(timers)\n\t}\n\treturn times.timer\n}\n\nfunc (th *timerHandler) add(key timerKey, newFire fireElement) {\n\tbyKeys, ok := th.toFire[newFire.firing]\n\tif !ok {\n\t\tbyKeys = th.userKeysSetPool.Get().(map[string]set[timerKey])\n\t\tth.toFire[newFire.firing] = byKeys\n\t\theap.Push(&th.order, newFire.firing) // We only need to add a firing order when inserting.\n\t}\n\ttimers, ok := byKeys[string(newFire.timer.keyBytes)]\n\tif !ok {","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/runners/prism/internal/engine/timers.go#L311-L347","documentation":"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.","triggerScenarios":"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.","commonSituations":"TestStream-driven tests replaying events out of order, pipelines setting and clearing timers concurrently across bundles, or prism version bugs in timer handling.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Guard removal: only clear a timer if it still exists\nif h.TimerExists(userKey, key) {\n    h.ClearTimer(userKey, key)\n}","typeGuard":null,"tryCatchPattern":"func safeRemove(h *timerHandler, userKey string, key timerKey) (recovered any) {\n    defer func() { recovered = recover() }()\n    h.FireAt(userKey, key)\n    return nil\n}","preventionTips":["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"],"tags":["go","panic","timer","internal-state","beam-prism"],"backgroundTag":"internal-invariant-violation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}