fix(notifications): deliver Telegram frames when the paired chat is not a forum - #3897
Merged
Yeachan-Heo merged 3 commits intoAug 6, 2026
Conversation
…ot a forum A paired private chat whose bot has no Threaded Mode answers createForumTopic with "Bad Request: the chat is not a forum". That description was not a recognized capability refusal, and the suppressed/rejected verdict lived in caller-local flags while getOrCreateTopic shares one in-flight creation, so every awaiter that joined the shared promise rethrew and dropped its frame - identity headers published after /resume, asks, and context updates never reached the chat. The rejection now travels as typed errors so every awaiter classifies it identically, the non-forum description counts as a capability refusal, and a confirmed refusal is latched so later frames stop re-issuing a rejected createForumTopic per message. Lore-id: 7c3a1f95 Confidence: high Scope-risk: narrow Reversibility: easy Tested: concurrent identity/ask frames against a non-forum private chat deliver flat with a single createForumTopic attempt Not-tested: live Telegram bot with Threaded Mode enabled mid-run (latch requires daemon restart)
yazzang-homelab
force-pushed
the
fix/telegram-private-chat-topic-refusal
branch
from
August 5, 2026 23:24
0afa50e to
e926f2e
Compare
Contributor
Author
|
Rebased onto current Re-verified on the new base: |
added 2 commits
August 6, 2026 10:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fix Telegram notification frames being dropped in a paired private chat whose bot has no Threaded Mode.
isThreadedModeCapabilityRefusalnow recognizes Telegram's real reply for that chat:Bad Request: the chat is not a forum.createForumTopicmoved from caller-local flags into typed errors (TopicCreationSuppressed,TopicCreationRejected), so every awaiter of the shared in-flight creation classifies the same rejection identically.createForumTopiconce per message.Why
TopicRegistry.getOrCreateTopicde-duplicates concurrent creations behind one in-flight promise. Only the caller that actually ran the create callback setcreationSuppressed/creationRejected; any frame that joined the shared promise saw both flagsfalse, fell through to the fail-closed branch, and rethrew:That frame is then dropped instead of being flat-delivered to the private chat — observed 10 times in one day on a live install (
gjc 0.12.12), and the reason identity headers published after/resume(the renamed session) and pending asks never arrive.Verified against the live Bot API for a paired private chat:
{"ok": false, "error_code": 400, "description": "Bad Request: the chat is not a forum"}That description matched none of the refusal patterns, so the deterministic flat-delivery path was never taken and the daemon retried the rejected create for every single frame.
Testing
private chat without Threaded Mode: concurrent frames all deliver flatinpackages/coding-agent/test/notifications-telegram-daemon.test.ts: with a slow non-forum rejection, a concurrentidentity_header+action_neededpair must both deliver flat, a followingcontext_updatemust deliver, and only onecreateForumTopicattempt may be made. It fails ondevwith the exact production error and passes with this change.bun test packages/coding-agent/test/notifications-telegram-daemon.test.ts— 553 pass, 0 fail.bun test scripts/telegram-daemon-generation-guard.test.ts— 48 pass;scripts/telegram-daemon-generation-guard.ts --validate-current-treeand the base/head run (v43 no protected changes) are clean.bun --cwd=packages/coding-agent run check— clean.GJC verdict
devbun checkpasses