Skip to content

fix(discord): truncate auto-thread and handoff thread names by UTF-16 units - #60252

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

fix(discord): truncate auto-thread and handoff thread names by UTF-16 units#60252
pierrenode wants to merge 1 commit into
NousResearch:mainfrom
pierrenode:fix/discord-thread-name-utf16-truncation

Conversation

@pierrenode

Copy link
Copy Markdown
Contributor

What does this PR do?

_derive_auto_thread_name() and create_handoff_thread() in plugins/platforms/discord/adapter.py cap Discord thread names with a Python code-point slice (content[:80], name[:80]), but Discord validates the name field in UTF-16 code units (100 max). An emoji-heavy first message (auto-threading) or handoff name can pass the code-point cap while exceeding 100 UTF-16 units, so create_thread() is rejected with error 50035 and the thread is silently never created.

This is the sibling of rename_thread() / gateway/run.py::_sanitize_discord_thread_title(), which were already migrated to utf16_len/_prefix_within_utf16_limit — those two rename a thread after semantic titling; _derive_auto_thread_name() and create_handoff_thread() construct the name at creation time and were missed by that pass.

Fix: route both through the same utf16_len/_prefix_within_utf16_limit helpers already imported in this module. No behavior change for ASCII names.

Related Issue

No separate issue filed for this specific gap (found via sibling-site review after the recent UTF-16 truncation fixes to rename_thread() and the forum-thread-name path).

Type of Change

  • 🐛 Bug fix

Changes Made

  • plugins/platforms/discord/adapter.py: _derive_auto_thread_name() and create_handoff_thread() now truncate with utf16_len/_prefix_within_utf16_limit instead of code-point slices (+12/-5 lines)
  • tests/gateway/test_discord_slash_commands.py: regression tests for both functions with 90-emoji names; verified RED without the fix (157/160 UTF-16 units, over the 80 budget) and GREEN with it

How to Test

uv run --frozen --extra dev python -m pytest tests/gateway/test_discord_slash_commands.py -v --override-ini="addopts="

Mutation-verified: reverting the fix locally makes both new tests fail with assert 157 <= 80 / assert 160 <= 80.

Checklist

  • Contributing Guide okundu | Conventional Commits | Duplicate PR yok
  • Sadece bu fix | Tests eklendi | Platform: macOS
  • Docs — N/A | Cross-platform — N/A

@alt-glitch alt-glitch added type/bug Something isn't working 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 P3 Low — cosmetic, nice to have labels Jul 7, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for finding the still-live auto-thread and handoff truncation gap. Current main confirms both reported code-point slices at plugins/platforms/discord/adapter.py:5332-5335 and :5495-5521, and the proposed use of the existing UTF-16 helpers matches the current semantic-rename implementation.

Problems

  • The same creation-time class remains in native /thread: _create_thread() only strips name at plugins/platforms/discord/adapter.py:5256 before supplying it to both create_thread() calls at :5279-5299.
  • Forum thread names still use first_line[:100] at plugins/platforms/discord/adapter.py:7787-7794; those names flow to forum creation at :2119-2127, :2188-2199, and :7975-8033.

Suggested changes

  • Extend this UTF-16 pass to those sibling creation paths using _prefix_within_utf16_limit() and each path's intended budget.
  • Add emoji-heavy assertions for /thread and forum creation, alongside the two good regressions already proposed here.

Automated hermes-sweeper review.

… units

_derive_auto_thread_name() and create_handoff_thread() cap Discord thread
names with a Python code-point slice ([:80]), but Discord validates the
`name` field in UTF-16 code units (100 max). An emoji-heavy first message
or handoff name can pass the code-point cap while exceeding 100 UTF-16
units, so create_thread() is rejected with error 50035 and the auto-thread
or handoff thread is silently never created.

This is the sibling rename_thread()/_sanitize_discord_thread_title()
(gateway/run.py) were already fixed to use utf16_len/_prefix_within_utf16_limit
for — those two functions rename a thread after semantic titling; these
two construct the thread name at creation time and were missed.

Fix: route both through the same utf16_len/_prefix_within_utf16_limit
helpers already imported in this module. No behavior change for ASCII
names (existing test_auto_create_thread_truncates_long_names still passes
unmodified).

Widen to the two remaining creation-time sites that share the same class
of bug:

- `_create_thread()` (the native /thread slash command): validates the
  explicit user-supplied name against the UTF-16 limit and returns a
  clear error rather than silently truncating input the user typed on
  purpose — different UX from the auto-generated-name sites, which
  already truncate.
- `_derive_forum_thread_name()`: forum-post thread names derived from the
  first line of a message had the same raw `first_line[:100]` code-point
  slice; now routed through `_prefix_within_utf16_limit`.
@pierrenode
pierrenode force-pushed the fix/discord-thread-name-utf16-truncation branch from a74fdb7 to 00bb1d6 Compare August 11, 2026 15:58
@pierrenode

Copy link
Copy Markdown
Contributor Author

Rebased onto current `upstream/main` — production code (`plugins/platforms/discord/adapter.py`) auto-merged cleanly, fix intact. The test file conflict was upstream's own pruning of several pre-existing `_auto_create_thread` tests unrelated to this fix — kept upstream's pruning, restored only this PR's own new UTF-16 regression test.

Mutation-verified: reverting `_derive_auto_thread_name`'s truncation to code-point slicing breaks the new test (157 UTF-16 units instead of ≤80). Full `tests/gateway/test_discord_slash_commands.py` (19 tests) passes. Ruff clean. Fresh competitor search: #60196 (forum thread names, `_derive_forum_thread_name`) touches a different, sibling function — no overlap with this PR's `_derive_auto_thread_name`/`create_handoff_thread`.

Squashed to a single commit on top of current `upstream/main`.

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.

3 participants