Summary
On a Linux systemd-user gateway running OpenClaw 2026.6.11-beta.1 (c862a64), a Telegram direct-message update became stuck in channel_ingress_events as pending and was retried continuously after every replay failed with:
reply session initialization conflicted for agent:main:telegram:direct:<telegram-user-id>
The gateway itself stayed healthy and reachable, but Telegram DM processing was effectively blocked behind the poisoned pending update. A later Telegram update for the same DM remained pending with attempts=0 because the earlier update never cleared.
This looks related to #96698 / #96699 and #96550, but this report is for a Telegram DM on 2026.6.11-beta.1, where the retry loop is still observable in the installed npm runtime.
Environment
- OpenClaw:
2026.6.11-beta.1 (c862a64)
- Node:
v26.1.0 via nvm
- OS: Linux
7.1.1-070101-generic x64
- Service: systemd user service
openclaw-gateway.service
- Gateway mode: local loopback
- Gateway port:
24619
- Channel: Telegram direct message, polling / isolated ingress
- Config shape:
channels.telegram.dmPolicy = allowlist, one allowed sender
Gateway health was OK:
curl http://127.0.0.1:24619/health
{"ok":true,"status":"live"}
Service was active:
openclaw-gateway.service loaded active running OpenClaw Gateway (v2026.6.11-beta.1)
ExecStart=.../openclaw/dist/index.js gateway --port 24619
Only one OpenClaw gateway process was running.
Observed behavior
Gateway logs repeatedly showed the same Telegram update being replayed and failing:
[telegram] Inbound message telegram:<user-id> -> @<bot> (direct, 3 chars)
[diagnostic] message dispatch completed: channel=telegram sessionId=unknown sessionKey=agent:main:telegram:direct:<user-id> source=replyResolver outcome=error duration=... error="Error: reply session initialization conflicted for agent:main:telegram:direct:<user-id>"
[diagnostic] message processed: channel=telegram chatId=telegram:<user-id> messageId=<message-id> sessionId=<session-id> sessionKey=agent:main:telegram:direct:<user-id> outcome=error duration=... error="Error: reply session initialization conflicted for agent:main:telegram:direct:<user-id>"
[telegram] dispatch failed: Error: reply session initialization conflicted for agent:main:telegram:direct:<user-id>
[telegram] [diag] spooled update <update-id> failed; keeping for retry: TelegramSpooledReplayProcessingError in middleware: telegram spooled update processing failed: Error: reply session initialization conflicted for agent:main:telegram:direct:<user-id>
The same messageId was logged over and over. During a short watch, the same inbound message was retried about twice per second.
channel_ingress_events showed two pending Telegram updates for the same account:
queue_name event_id channel_id account_id status attempts last_attempt_at
---------------------- ---------------- ---------- ---------- ------- -------- ---------------
["telegram","default"] <update-id-1> telegram default pending 900+ <recent time>
["telegram","default"] <update-id-2> telegram default pending 0 null
The second update was not processed because the first pending update kept re-entering the retry loop.
The file spool directory was empty:
~/.openclaw/telegram/ingress-spool-default
# no files
So the stuck state was in SQLite channel_ingress_events, not an on-disk spool file.
Local investigation notes
The thrown error comes from the reply session initialization path:
// dist/get-reply-*.js
if (!committed.ok) {
if (!staleSnapshotRetried) return await initSessionStateAttempt(params, true);
throw new Error(`reply session initialization conflicted for ${sessionKey}`);
}
commitReplySessionInitialization() compares a full-entry revision:
function createReplySessionInitializationRevision(entry) {
return JSON.stringify(entry ?? null);
}
The Telegram retry path treats this as retryable and releases the update back to pending:
[telegram][diag] spooled update <update-id> failed; keeping for retry: TelegramSpooledReplayProcessingError ... reply session initialization conflicted ...
At the time of inspection, resolveNonRetryableSpooledUpdateFailure() only recognized a small set of non-retryable cases, so this conflict stayed retryable and hot-looped.
Why this may not be fully covered by existing reports
Related existing items:
This report adds a current Telegram DM repro on 2026.6.11-beta.1 (c862a64), with the stuck update in SQLite channel_ingress_events, not file spool, and with a direct DM session key:
agent:main:telegram:direct:<user-id>
If #96550/#96699 are expected to cover this, it would be useful to know whether they have landed in a release newer than 2026.6.11-beta.1, or whether Telegram DM + SQLite ingress still needs separate coverage.
Expected behavior
A transient reply-session initialization conflict should not permanently block the Telegram DM lane.
At minimum, one of these should happen:
- retry with bounded backoff instead of immediate hot-looping;
- retry after the active/busy session settles;
- dead-letter after a poison retry threshold if the same error signature repeats;
- allow later updates on unrelated lanes to continue, and preserve same-DM ordering without hammering the gateway.
Actual behavior
One pending Telegram DM update was retried hundreds/thousands of times, repeatedly failing with the same reply-session initialization conflict. Later DM updates stayed pending behind it.
Operational impact
- Gateway
/health remains live, so basic monitoring reports healthy.
- Telegram direct-message UX is broken: messages appear ignored because inbound processing is blocked behind the poisoned update.
- Logs are polluted by repeated retry lines.
- The retry loop continues without operator intervention.
Useful diagnostic queries
These were useful to identify the stuck state:
select queue_name,event_id,channel_id,account_id,status,lane_key,received_at,updated_at,attempts,last_attempt_at,substr(last_error,1,220) last_error,failed_reason,failed_at,completed_at
from channel_ingress_events
where payload_json like '%<telegram-user-id>%'
order by updated_at desc;
select event_id,status,attempts,
json_extract(payload_json,'$.update.update_id') as update_id,
json_extract(payload_json,'$.update.message.message_id') as message_id,
json_extract(payload_json,'$.update.message.chat.id') as chat_id,
json_extract(payload_json,'$.update.message.from.id') as from_id
from channel_ingress_events
where status = 'pending';
Workaround
I did not apply a destructive workaround while collecting this report. The likely temporary unblock would be to dead-letter or remove the specific poisoned channel_ingress_events row, then restart or allow the queue to drain, but that would drop the affected user message.
Summary
On a Linux systemd-user gateway running OpenClaw
2026.6.11-beta.1 (c862a64), a Telegram direct-message update became stuck inchannel_ingress_eventsaspendingand was retried continuously after every replay failed with:The gateway itself stayed healthy and reachable, but Telegram DM processing was effectively blocked behind the poisoned pending update. A later Telegram update for the same DM remained pending with
attempts=0because the earlier update never cleared.This looks related to #96698 / #96699 and #96550, but this report is for a Telegram DM on
2026.6.11-beta.1, where the retry loop is still observable in the installed npm runtime.Environment
2026.6.11-beta.1 (c862a64)v26.1.0via nvm7.1.1-070101-genericx64openclaw-gateway.service24619channels.telegram.dmPolicy = allowlist, one allowed senderGateway health was OK:
Service was active:
Only one OpenClaw gateway process was running.
Observed behavior
Gateway logs repeatedly showed the same Telegram update being replayed and failing:
The same
messageIdwas logged over and over. During a short watch, the same inbound message was retried about twice per second.channel_ingress_eventsshowed two pending Telegram updates for the same account:The second update was not processed because the first pending update kept re-entering the retry loop.
The file spool directory was empty:
So the stuck state was in SQLite
channel_ingress_events, not an on-disk spool file.Local investigation notes
The thrown error comes from the reply session initialization path:
commitReplySessionInitialization()compares a full-entry revision:The Telegram retry path treats this as retryable and releases the update back to pending:
At the time of inspection,
resolveNonRetryableSpooledUpdateFailure()only recognized a small set of non-retryable cases, so this conflict stayed retryable and hot-looped.Why this may not be fully covered by existing reports
Related existing items:
reply session initialization conflictedshape, but on Discord and OpenClaw2026.6.10.skillsSnapshotpersisted/hydrated revision mismatch for reply session initialization.This report adds a current Telegram DM repro on
2026.6.11-beta.1 (c862a64), with the stuck update in SQLitechannel_ingress_events, not file spool, and with a direct DM session key:If #96550/#96699 are expected to cover this, it would be useful to know whether they have landed in a release newer than
2026.6.11-beta.1, or whether Telegram DM + SQLite ingress still needs separate coverage.Expected behavior
A transient reply-session initialization conflict should not permanently block the Telegram DM lane.
At minimum, one of these should happen:
Actual behavior
One pending Telegram DM update was retried hundreds/thousands of times, repeatedly failing with the same reply-session initialization conflict. Later DM updates stayed pending behind it.
Operational impact
/healthremains live, so basic monitoring reports healthy.Useful diagnostic queries
These were useful to identify the stuck state:
Workaround
I did not apply a destructive workaround while collecting this report. The likely temporary unblock would be to dead-letter or remove the specific poisoned
channel_ingress_eventsrow, then restart or allow the queue to drain, but that would drop the affected user message.