hermes - ✅(Solved) Fix Slack slash-command replies can be silently truncated or dropped when response_url delivery fails [1 pull requests, 2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#19688Fetched 2026-05-05 06:05:34
View on GitHub
Comments
2
Participants
2
Timeline
7
Reactions
0
Author
Participants
Timeline (top)
labeled ×4commented ×2cross-referenced ×1

Error Message

  • logs non-200/exception from the response_url POST but returns SendResult(success=True).
  • return SendResult(success=False, error=...) when the response_url POST fails and no fallback delivery succeeds.

Root Cause

The Slack slash-command ephemeral reply path optimizes for replacing a single ephemeral acknowledgement, but it conflates "the user saw an initial ack" with successful delivery of the final command output. It also drops every chunk after the first one.

Fix Action

Fixed

PR fix notes

PR #19701: fix(gateway/slack): report failure and deliver all chunks for slash-command replies

Description (problem / solution / changelog)

Summary

Fix two bugs in the Slack slash-command ephemeral reply path (_send_slash_ephemeral):

  1. Silent truncation: Only the first chunk of multi-chunk responses was delivered via response_url. Follow-up chunks were silently dropped, so users with long /help, /commands, or /model output only saw partial responses.

  2. False success on failure: When the response_url POST failed (non-200 status or exception), the method returned SendResult(success=True), making the caller believe delivery succeeded even though the user may have only seen the initial "Running …" acknowledgement.

Changes

  • gateway/platforms/slack.py:

    • _send_slash_ephemeral now accepts chat_id, reply_to, and metadata parameters
    • After replacing the ephemeral ack with the first chunk, any remaining chunks are posted as normal channel messages via chat_postMessage
    • Returns SendResult(success=False, error="response_url delivery failed", retryable=True) when the response_url POST fails
    • Updated call site in send() to pass through chat_id, reply_to, and metadata
  • tests/gateway/test_slack.py: Updated the two existing tests (test_send_slash_ephemeral_fallback_on_post_failure and test_send_slash_ephemeral_fallback_on_exception) to assert the corrected success=False + retryable=True behavior.

Testing

All 180 Slack gateway tests pass.

Closes #19688

Changed files

  • gateway/platforms/slack.py (modified, +51/-18)
  • tests/gateway/test_slack.py (modified, +7/-4)
RAW_BUFFERClick to expand / collapse

Bug Description

Slack native slash-command replies can be silently truncated or lost.

When a Slack slash command is handled through the stored response_url path, Hermes formats the response, splits/truncates it, then sends only the first chunk back to Slack. If the response_url POST fails or has expired, the adapter logs a warning but still returns SendResult(success=True), so the caller treats delivery as successful even though the user may only see the initial ephemeral "Running ..." acknowledgement.

This affects user-visible command replies such as long /help, /commands, /model, or other native slash-command responses.

Inspected against main commit af6f9bc2a12682b06fb3632acf5a9cbf01e74a85.

Steps to Reproduce

Static code path:

  1. Trigger a Slack native slash command that produces a long response or whose response_url delivery fails/expires.
  2. The message is routed through SlackPlatform.send().
  3. send() finds a stored slash-command context and calls _send_slash_ephemeral().
  4. _send_slash_ephemeral() uses only chunks[0] and returns success even after a failed response_url POST.

Expected Behavior

Hermes should either:

  • deliver the full command response, possibly by posting follow-up chunks or falling back to normal Slack channel/thread delivery when appropriate, or
  • return a failed SendResult when response_url delivery fails so the caller can surface/retry the delivery failure.

Actual Behavior

  • Long slash-command output is reduced to the first chunk.
  • A failed response_url POST is logged but reported as SendResult(success=True).
  • The user can be left with only the initial ephemeral acknowledgement or incomplete command output.

Evidence

  • gateway/platforms/slack.py:451-457
    • formats the slash-command response, calls truncate_message(...), then keeps only chunks[0].
  • gateway/platforms/slack.py:463-483
    • logs non-200/exception from the response_url POST but returns SendResult(success=True).
  • gateway/platforms/slack.py:713-723
    • routes pending native slash-command replies exclusively through _send_slash_ephemeral().

Affected Component

Gateway / Slack

Environment

Static analysis of current main; no local environment-specific behavior required.

Prior Art Checked

I searched existing issues and PRs for:

  • Slack slash command response_url success fallback
  • Slack ephemeral response_url truncated first chunk
  • replace_original SendResult(success=True)

I did not find an exact existing issue or PR covering this response_url truncation/failure-success path.

Root Cause Analysis

The Slack slash-command ephemeral reply path optimizes for replacing a single ephemeral acknowledgement, but it conflates "the user saw an initial ack" with successful delivery of the final command output. It also drops every chunk after the first one.

Proposed Fix

One possible fix:

  • preserve the first ephemeral replacement for short responses;
  • for multi-chunk command output, post additional chunks through normal Slack delivery or a supported follow-up mechanism;
  • return SendResult(success=False, error=...) when the response_url POST fails and no fallback delivery succeeds.

Exact fallback behavior should match the maintainers' preferred Slack UX for ephemeral vs public/threaded command output.

extent analysis

TL;DR

Modify the _send_slash_ephemeral() function to handle multi-chunk command output and return a failed SendResult when response_url delivery fails.

Guidance

  • Review the truncate_message() function to determine why it's truncating the response to the first chunk.
  • Consider implementing a fallback mechanism to post additional chunks through normal Slack delivery when response_url delivery fails.
  • Update the _send_slash_ephemeral() function to return SendResult(success=False) when the response_url POST fails.
  • Investigate the Slack API to determine the best approach for posting follow-up chunks, such as using the chat.postMessage method.

Example

def _send_slash_ephemeral(...):
    # ...
    chunks = truncate_message(response)
    if len(chunks) > 1:
        # Post additional chunks through normal Slack delivery
        for chunk in chunks[1:]:
            # Use the chat.postMessage method to post the chunk
            pass
    # ...
    try:
        # Post the first chunk to the response_url
        response = requests.post(response_url, json={'text': chunks[0]})
        response.raise_for_status()
    except requests.RequestException as e:
        # Return a failed SendResult if the POST fails
        return SendResult(success=False, error=str(e))

Notes

The exact implementation of the fallback mechanism will depend on the desired Slack UX for ephemeral vs public/threaded command output. The chat.postMessage method may need to be used to post follow-up chunks.

Recommendation

Apply a workaround by modifying the _send_slash_ephemeral() function to handle multi-chunk command output and return a failed SendResult when response_url delivery fails. This will ensure that users receive the full command response and that delivery failures are properly reported.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING