-
-
Notifications
You must be signed in to change notification settings - Fork 80.7k
channel_ingress_events (SQLite): stale claims never recovered after session crash — Telegram DM deadlocks #90945
Copy link
Copy link
Open
Labels
P1High-priority user-facing bug, regression, or broken workflow.High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.Channel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.Session, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.
Description
Metadata
Metadata
Assignees
Labels
P1High-priority user-facing bug, regression, or broken workflow.High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.Channel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.Session, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.
Type
Fields
Priority
None yet
channel_ingress_events (SQLite): stale claims never recovered — deadlocks Telegram sessions
OpenClaw version:
2026.6.1Channel: Telegram DM
OS: Linux (CachyOS, kernel 7.0.11)
Summary
When a session dies mid-turn,
channel_ingress_eventsrows stay inclaimedstate permanently. Every new message into that session gets claimed by a worker, which also fails, leaving another stuckclaimedrow. The channel becomes silently unresponsive until manually unblocked via direct SQLite write.This happened twice in the same session within ~1 hour on 2026-06-06.
Steps to reproduce
kill -HUPon gateway PID, or unhandled rejection)channel_ingress_events:claimedrow, never releasedWhy the existing recovery does NOT fire (dist analysis on v2026.6.1)
Issue #90940 was closed as 'already implemented'. After analysing
/app/dist/on v2026.6.1, the existing recovery covers a different code path — the file-based spool, not SQLite.What IS implemented ✅
recoverStaleTelegramSpooledUpdateClaimsinmonitor-polling.runtime-C_Buepuh.js:This recovers stale claims in the file-based spool (
~/.openclaw/telegram/ingress-spool-default/). Has both a TTL (6h) and a live-process guard. Works correctly.What is NOT implemented ❌
The stuck claims are in
channel_ingress_events(SQLite).Evidence:
1.
claimNextis never called externallyDefined in the queue module, never imported anywhere else. The
claimNextpath (which callsrecoverStaleClaimswhenstaleMsis passed) is dead code.2.
openChannelIngressQueuehas exactly one callercreateTelegramIngressQueueinmonitor-polling.runtimewraps the spool directory path, not the main SQLite ingress queue.3. No startup sweep
On gateway boot, there is no code that iterates
claimedrows inchannel_ingress_events, checks ifclaim_ownerPID is still alive, and resets dead claims topending. TheprocessExists()function exists inmonitor-polling.runtimebut is only wired to the spool path.The gap
Proposed fix
Option A — Startup sweep (simplest)
On gateway start, iterate
claimedrows inchannel_ingress_eventsand reset those whereclaim_ownerPID is no longer alive (same logic asprocessExistsalready used for spool).Option B — Pass staleMs to claimNext
At the call site that drains
channel_ingress_events, passstaleMs:Option C — Periodic background reaper
A background timer (e.g. every 5 min) calls:
Workaround
Script cron every 5 min, resets claims older than 10 minutes, notifies via Telegram.
Protecting the most recently claimed event in case it is actively being processed.