vercel / vercel/chat

Telegram silently truncates long messages instead of splitting them

Open
#824 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
2.4k
Forks
314
Avg merge
1d 18h
Merged PRs (30d)
63

Description

Bug Description

@chat-adapter/telegram silently discards the remainder of long messages. postMessage() renders the postable content, passes the rendered text through truncateForTelegram(..., 4096, ...), and sends only the truncated result.

This is especially surprising for { markdown } messages: MarkdownV2 escaping expands the wire payload, so source text can be cut substantially before its own length reaches the apparent platform boundary. The caller receives a successful SentMessage and has no indication that content was lost.

This is the concrete Telegram symptom of the broader contract problem discussed in #408.

Steps to Reproduce
  1. Create a Chat SDK bot using @chat-adapter/telegram.
  2. In a Telegram handler, post a Markdown response whose rendered MarkdownV2 output exceeds 4,096 characters.
  3. Trigger the handler from Telegram.
  4. Observe that Telegram receives one message ending in an ellipsis and never receives the remainder.
Expected Behavior

Long Telegram posts should not silently lose content. When configured to split long messages, the adapter should send the complete response as ordered consecutive messages, with each payload inside Telegram's limit and with valid formatting.

Short messages should continue to produce one Telegram message.

Actual Behavior

Only one Telegram message is sent. It is truncated to 4,096 characters after rendering, with an ellipsis appended. Everything after the cutoff is discarded.

Code Sample
import { createTelegramAdapter } from '@chat-adapter/telegram';
import { Chat } from 'chat';

const bot = new Chat({
  userName: 'mybot',
  adapters: {
    telegram: createTelegramAdapter({ mode: 'polling' }),
  },
});

bot.onNewMention(async (thread) => {
  const longMarkdown = Array.from(
    { length: 200 },
    (_, index) => `## Section ${index + 1}\n\n- Result with punctuation: value_${index}.`,
  ).join('\n\n');

  await thread.post({ markdown: longMarkdown });
});
Chat SDK Version

chat@4.28.1, @chat-adapter/telegram@4.28.1

Node.js Version

24.14.0

Platform Adapter

Telegram

Operating System

macOS

Additional Context

In a real n8n Agent reproduction, the stored assistant response contained 6,291 source characters. Telegram cut the visible response around source character 3,932 because MarkdownV2 escaping expanded the rendered payload to the adapter's 4,096-character truncation boundary.

Current main still retains truncateForTelegram() for classic/fallback Telegram message paths. Newer rich-message support raises the ceiling for supported Bot API versions, but it does not eliminate silent data loss in fallback paths or above the rich-message limit.

A useful adapter-level resolution would be an explicit long-message strategy such as the "split" option proposed in #408. Splitting belongs in the adapter because it owns final rendering, Telegram-specific limits, formatting validity, and the semantics of returning one SentMessage for multiple API posts.

Image

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the Telegram adapter's postMessage() path and truncateForTelegram(), then read the broader long-message contract discussed in #408. Verify rendered MarkdownV2 and fallback paths; done means a configured split strategy sends complete, ordered, validly formatted chunks within Telegram's limit, while short messages remain single sends and no content is silently discarded.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.