Skip to content

fix(telegram): prevent surrogate pair splitting in truncate_message - #11649

Closed
truenorth-lj wants to merge 1 commit into
NousResearch:mainfrom
truenorth-lj:fix/telegram-utf16-surrogate-split
Closed

truenorth-lj wants to merge 1 commit into
NousResearch:mainfrom
truenorth-lj:fix/telegram-utf16-surrogate-split

Conversation

@truenorth-lj

Copy link
Copy Markdown
Contributor

Summary

Fixes #11467 — Telegram message splitting can slice UTF-16 surrogate pairs, causing UnicodeEncodeError delivery failures.

When model APIs deliver astral-plane characters (emoji like 🎩 U+1F3A9) as JSON-escaped surrogate pairs (\uD83C\uDFA9), some decoders store them as two separate code units in the Python string. truncate_message() could slice between the high and low surrogate, producing a lone surrogate that causes UnicodeEncodeError: 'utf-16-le' codec can't encode character '\udfa9' on delivery.

Changes

  • utf16_len(): use surrogatepass error handler so lone surrogates are counted as one UTF-16 code unit each instead of raising
  • truncate_message(): after finding a natural break point (newline/space/backtick adjustment), check that split_at does not land between a high surrogate (U+D800..U+DBFF) and its low surrogate (U+DC00..U+DFFF); if it does, step back by one to keep the pair together

Files changed

  • gateway/platforms/base.py — core fix in utf16_len and truncate_message
  • tests/gateway/test_platform_base.py — regression test that constructs a string with surrogate-pair code units and verifies no chunk contains a lone surrogate after splitting

Test plan

🤖 Generated with Claude Code

When model APIs deliver astral-plane characters (emoji like 🎩) as
JSON-escaped surrogate pairs (\uD83C\uDFA9), some decoders store them
as two separate code units in the Python string.  truncate_message()
could slice between the high and low surrogate, producing a lone
surrogate that causes UnicodeEncodeError on delivery.

Two fixes:
- utf16_len: use 'surrogatepass' error handler so lone surrogates are
  counted instead of raising
- truncate_message: after finding a natural break point, check that
  split_at does not land between a high and low surrogate

Closes #11467

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter labels Apr 24, 2026
@teknium1

Copy link
Copy Markdown
Collaborator

Closing — issue #11467 is resolved on current main, so this PR is no longer needed. Thanks for the contribution; your work and analysis are appreciated.

@teknium1 teknium1 closed this Jun 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/telegram Telegram bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Telegram message splitting can slice UTF-16 surrogate pairs, causing delivery failures

3 participants