Skip to content

fix(discord): cap forum thread names by UTF-16 units, not code points - #60196

Open
briandevans wants to merge 1 commit into
NousResearch:mainfrom
briandevans:fix/discord-forum-thread-name-utf16
Open

fix(discord): cap forum thread names by UTF-16 units, not code points#60196
briandevans wants to merge 1 commit into
NousResearch:mainfrom
briandevans:fix/discord-forum-thread-name-utf16

Conversation

@briandevans

Copy link
Copy Markdown
Contributor

This is a sibling follow-up to #60113

What does this PR do?

_derive_forum_thread_name in plugins/platforms/discord/adapter.py caps the
derived Discord forum thread name with first_line[:100] — a code-point slice —
but Discord validates the thread name field in UTF-16 code units (100 max).

A message whose first line opens with emoji / non-BMP text (agents commonly lead
with an emoji header) can exceed 100 UTF-16 units while passing the code-point
cap, so create_thread(name=...) fails with error 50035 ("Must be 100 or fewer
in length") and the entire forum reply is dropped (SendResult(success=False)),
not merely clipped. This is the sibling the UTF-16 hardening in #60113 (component
labels) missed; the adapter already imports _prefix_within_utf16_limit/utf16_len
for exactly this purpose.

Related Issue

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • plugins/platforms/discord/adapter.py: _derive_forum_thread_name now returns
    _prefix_within_utf16_limit(first_line, 100) instead of first_line[:100]
    (and the docstring reflects the UTF-16 unit limit).
  • tests/gateway/test_discord_clarify_buttons.py: add
    test_forum_thread_name_capped_by_utf16_units.

How to Test

  1. _derive_forum_thread_name("\U0001F600" * 100) — 100 emoji is 200 UTF-16
    units under the old code-point cap; after this change the result is clamped
    to <= 100 units without splitting a surrogate pair.
  2. ASCII behavior is unchanged: 200 x still clamps to exactly 100 units.
  3. pytest tests/gateway/test_discord_clarify_buttons.py tests/gateway/test_discord_send.py -q → 40 passed. The new test fails before the fix (200 > 100), passes after.

Follow-up (out of scope here): the Choice.name and describe-hint [:100] caps
in the same adapter are the remaining code-point siblings and can be migrated
separately.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/gateway/test_discord_clarify_buttons.py tests/gateway/test_discord_send.py -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15 (Darwin 25.4)

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — updated the _derive_forum_thread_name docstring
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) — pure string logic, platform-independent

_derive_forum_thread_name capped the derived Discord forum thread name with
first_line[:100] — a Python code-point slice — but Discord validates the
thread name field in UTF-16 code units (100 max). A first line opening with
emoji or non-BMP text (agents commonly lead with an emoji header) can exceed
100 UTF-16 units while passing the code-point cap, so create_thread fails
with error 50035 and the entire forum reply is dropped
(SendResult(success=False)), not merely clipped. Switch to
_prefix_within_utf16_limit (already imported and used elsewhere in this
adapter) so the name never splits a surrogate pair and always stays within
Discord's limit. Sibling of the UTF-16 hardening in NousResearch#60113, which bounded
component labels but missed this path.
Copilot AI review requested due to automatic review settings July 7, 2026 11:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Discord forum-thread posting edge case where derived thread names could exceed Discord’s 100 UTF-16 code unit limit when the first line contains non-BMP characters (e.g., emoji), causing create_thread(name=...) to fail and drop the forum reply. It aligns forum thread-name truncation with the existing UTF-16-safe truncation approach already used elsewhere in the Discord adapter.

Changes:

  • Update _derive_forum_thread_name to cap by UTF-16 code units via _prefix_within_utf16_limit(..., 100) instead of slicing by Python code points ([:100]).
  • Add a regression test covering emoji-heavy and ASCII-heavy inputs to ensure derived forum thread names fit Discord’s UTF-16 budget.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
plugins/platforms/discord/adapter.py Switch forum thread-name truncation to UTF-16-unit-safe prefixing and update the docstring to reflect Discord’s actual validation unit.
tests/gateway/test_discord_clarify_buttons.py Add regression coverage ensuring forum thread-name derivation stays within the 100 UTF-16 code unit limit (emoji + ASCII cases).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins platform/discord Discord bot adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 7, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for isolating the forum-thread path. The proposed replacement of the current first_line[:100] at plugins/platforms/discord/adapter.py:7794 with the existing UTF-16 helper is correct: that value is used by both forum creation paths (:2119 and :7975), and _prefix_within_utf16_limit enforces the unit budget in gateway/platforms/base.py:156-172.

Problems

  • The same unit mismatch remains in auto-thread naming: plugins/platforms/discord/adapter.py:5332-5335 caps by code points before the names reach create_thread at :5355 and :5367. The handoff path has another 80-code-point cap at :5495, passed to creation at :5503 and :5521. An 80-emoji input exceeds an 80-unit budget.

Suggested changes

  • Apply the same UTF-16-safe cap to those two thread-name producers and add emoji coverage next to tests/gateway/test_discord_slash_commands.py:639.

Automated hermes-sweeper review.

@teknium1 teknium1 added the sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform label Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have platform/discord Discord bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants