Repository navigation
Conversation
…, surface API rejections Fixes Dokploy#5392.
| console.error( | ||
| `Telegram notification failed with status ${response.status}: ${await response.text()}`, | ||
| ); |
There was a problem hiding this comment.
Rejections Still Report Success
Telegram API rejections are logged, but sendTelegramNotification still resolves after a non-success response. As a result, testTelegramConnection returns true and the settings UI displays “Connection Success” even when Telegram rejects an invalid token, chat ID, or message. The sender must propagate the rejection to its caller instead of swallowing it.
There was a problem hiding this comment.
Fixed in 9daee3e: sendTelegramNotification now returns a real delivery boolean (false on non-2xx and on thrown errors), and testTelegramConnection throws when Telegram rejects the test message instead of reporting a false success. Covered by new red/green tests (rejection -> false, 2xx -> true).
| await sendTelegramNotification( | ||
| telegram, | ||
| `<b>⚠️ Build Failed</b>\n\n<b>Project:</b> ${projectName}\n<b>Application:</b> ${applicationName}\n<b>Type:</b> ${applicationType}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}\n\n<b>Error:</b>\n<pre>${errorMessage}</pre>`, | ||
| `<b>⚠️ Build Failed</b>\n\n<b>Project:</b> ${escapeTelegramHtml(projectName)}\n<b>Application:</b> ${escapeTelegramHtml(applicationName)}\n<b>Type:</b> ${escapeTelegramHtml(applicationType)}\n<b>Date:</b> ${format(date, "PP")}\n<b>Time:</b> ${format(date, "pp")}\n\n<b>Error:</b>\n<pre>${truncateTelegramText(escapeTelegramHtml(errorMessage))}</pre>`, |
There was a problem hiding this comment.
Only the error text is length-limited; the escaped project and application names remain unbounded. These names have no server-side maximum, and escaping can expand each character up to fivefold. A sufficiently long or markup-heavy name can therefore push the complete message beyond Telegram’s 4096-character limit, causing the build-failure notification to be rejected. Bound the assembled payload or reserve limited space for every dynamic field.
There was a problem hiding this comment.
Fixed in 9daee3e: escaped project, application, and type names are now each wrapped in truncateTelegramText(..., 200), so the composed message can never approach Telegram's 4096-char ceiling.
| return escapedText; | ||
| } | ||
|
|
||
| let truncated = escapedText.substring(0, maxLength); |
There was a problem hiding this comment.
Truncation Can Corrupt Unicode
substring(0, maxLength) truncates UTF-16 code units and can split a non-BMP character when an emoji or similar build-output character crosses the cutoff. This leaves a lone surrogate that is replaced during UTF-8 encoding, corrupting the final character before the ellipsis. Truncate by Unicode code points or back off when the cut falls inside a surrogate pair.
There was a problem hiding this comment.
Fixed in 9daee3e: truncateTelegramText now backs off one more code unit when the cut leaves a dangling high surrogate, so non-BMP characters (emoji in build output) cannot corrupt the payload. Regression test added - it is red against the pre-patch truncation.
- sendTelegramNotification now returns a real delivery boolean; testTelegramConnection throws on rejection instead of reporting a false success - wrap escaped project/application/type names in truncateTelegramText(..., 200) so a message can never approach Telegram's 4096-char ceiling (which Telegram answers with a silent 400) - truncateTelegramText backs off a dangling high surrogate at the cut so emoji and other non-BMP characters in build output cannot corrupt the JSON payload Tests: 9/9 green; the surrogate and delivery-result cases are red against the pre-patch source (surrogate cut adjusted to actually straddle the pair).
Fixes #5392.
Telegram build-error notifications were silently dropped on any substantial build failure, for three stacked reasons:
The Telegram branch now escapes all dynamic fields and truncates the escaped error text (with a guard against splitting an HTML entity at the cut point), matching the 800-character convention of the other channels, and sendTelegramNotification logs the status and response body when Telegram rejects a message.
Tests: test/notifications/telegram-text.test.ts covers escaping (including & ordering), truncation, entity-safe cuts, and that a pathological all-markup error still produces a sub-4096 payload. 6/6 green locally (vitest, test/vitest.config.ts).
The PR should not merge until Telegram API rejections propagate to callers so failed connection tests cannot report success.
Findings
Summary