openclaw - 💡(How to fix) Fix Telegram exec approval inline buttons fail due to callback_query sequentialization timeout [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#60503Fetched 2026-04-08 02:50:17
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

Root Cause

The Telegram bot uses grammY's sequentialize middleware, which processes all updates from the same chat sequentially. When an agent turn issues an exec command requiring approval:

  1. The agent turn is blocked waiting on exec.approval.waitDecision
  2. The approval card with inline buttons is sent to Telegram
  3. The user clicks a button immediately
  4. The resulting callback_query arrives via getUpdates polling
  5. However, the callback_query is queued behind the still-running agent turn due to sequentialize
  6. By the time the callback_query handler runs, Telegram's internal callback query timeout has expired
  7. answerCallbackQuery fails with query is too old and response timeout expired
  8. Simultaneously, the waitDecision resolves (agent turn interrupted or timed out), clearing the approval from memory
  9. exec.approval.resolve fails with unknown or expired approval id

Fix Action

Workaround

Set channels.telegram.execApprovals.enabled: false to disable inline buttons and fall back to text-based /approve <id> allow-once commands, which are processed as regular messages and do not suffer from this issue.

Code Example

03:40:31 [exec] obfuscation detected → approval created
03:42:28 [telegram] answerCallbackQuery failed: query is too old
03:42:28 [ws] exec.approval.waitDecision returned (116454ms)
03:42:30 [ws] exec.approval.resolve FAILED: unknown or expired approval id
03:42:30 [ws] plugin.approval.resolve FAILED: unknown or expired approval id
RAW_BUFFERClick to expand / collapse

Bug Description

Telegram exec approval inline buttons (Allow Once / Allow Always / Deny) consistently fail with ❌ Failed to submit approval when clicked by the user, even immediately after the approval card is sent.

Root Cause Analysis

The Telegram bot uses grammY's sequentialize middleware, which processes all updates from the same chat sequentially. When an agent turn issues an exec command requiring approval:

  1. The agent turn is blocked waiting on exec.approval.waitDecision
  2. The approval card with inline buttons is sent to Telegram
  3. The user clicks a button immediately
  4. The resulting callback_query arrives via getUpdates polling
  5. However, the callback_query is queued behind the still-running agent turn due to sequentialize
  6. By the time the callback_query handler runs, Telegram's internal callback query timeout has expired
  7. answerCallbackQuery fails with query is too old and response timeout expired
  8. Simultaneously, the waitDecision resolves (agent turn interrupted or timed out), clearing the approval from memory
  9. exec.approval.resolve fails with unknown or expired approval id

Evidence from Logs

03:40:31 [exec] obfuscation detected → approval created
03:42:28 [telegram] answerCallbackQuery failed: query is too old
03:42:28 [ws] exec.approval.waitDecision returned (116454ms)
03:42:30 [ws] exec.approval.resolve FAILED: unknown or expired approval id
03:42:30 [ws] plugin.approval.resolve FAILED: unknown or expired approval id

Pattern confirmed across 3 separate incidents (22:37, 02:11, 03:42), all showing the same callback_query sequentialization timeout.

Expected Behavior

Clicking the inline approval button should immediately process the approval, regardless of whether an agent turn is in progress.

Suggested Fix

callback_query updates for exec approvals should bypass the sequentialize middleware, or at minimum be processed in a separate concurrency lane from regular message updates. The approval resolution handler does not depend on the agent turn's sequential state and should be safe to process concurrently.

Workaround

Set channels.telegram.execApprovals.enabled: false to disable inline buttons and fall back to text-based /approve <id> allow-once commands, which are processed as regular messages and do not suffer from this issue.

Environment

  • OpenClaw: 2026.4.2 (d74a122)
  • Node: v22.22.2
  • OS: macOS (arm64)
  • Telegram: polling mode with proxy

extent analysis

TL;DR

To fix the issue with Telegram exec approval inline buttons failing, bypass the sequentialize middleware for callback_query updates related to exec approvals or process them in a separate concurrency lane.

Guidance

  • Identify the sequentialize middleware in the grammY setup and consider creating an exception for callback_query updates related to exec approvals.
  • Implement a separate concurrency lane for processing callback_query updates to prevent them from being queued behind agent turns.
  • As a temporary workaround, consider disabling inline buttons by setting channels.telegram.execApprovals.enabled: false and using text-based approval commands instead.
  • Review the logs to confirm that the callback_query timeout is the root cause of the issue and that the proposed fix addresses this specific problem.

Example

No specific code example is provided due to the complexity of the issue and the need for a customized solution based on the existing grammY setup.

Notes

The suggested fix requires careful consideration of the concurrency model and potential interactions between agent turns and approval processing. It is essential to ensure that bypassing the sequentialize middleware or creating a separate concurrency lane does not introduce other issues or inconsistencies in the system.

Recommendation

Apply the workaround by setting channels.telegram.execApprovals.enabled: false to disable inline buttons and use text-based approval commands, as this provides a temporary solution with minimal risk until a more permanent fix can be implemented.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING