Slack Message Delivery Failure: Diagnostic Guide for 'Couldn't Send Message'
Diagnose and fix Slack messages that fail to send, stay in 'sending,' or return 'Couldn't send message' using API checks, scope verification, and rate-limit handling.
15 Dec 2025, 05:11 UTC

A Slack message that stays in "sending" or returns "Couldn't send message" usually means the send request did not complete, not that Slack is unavailable. The useful takeaway is to isolate the failure—permission, rate limit, or content—before changing app settings or contacting support.
Recognizable Condition
- The message remains in a "sending" state and never appears in the channel.
- The client shows an error banner such as "Couldn't send message."
- An API call returns HTTP 429 or a JSON body with
ok: falseand errors likechannel_not_found,not_in_channel,ratelimited, ormsg_too_long.
Cause and Diagnostic Check
| Observation | Likely cause | First check |
|---|---|---|
| Failure in one channel only | App or user is not a member of that channel | conversations.info |
| All messages fail for one app | Missing or invalid OAuth scopes | auth.test |
| HTTP 429 response | Slack rate limit | Response headers |
| Long message or complex blocks | Message size or structure exceeds limits | Request body |
Ordered Checks
- Confirm the scope of the failure. Test the same message as a user and as an app. If only the app fails, the cause is likely token scopes or channel membership. If both fail, check network or workspace restrictions.
- Verify the token identity. Run this in a terminal or API client. You need a Slack bot or user token. Replace
$SLACK_TOKENwith your token.curl -X POST https://slack.com/api/auth.test \ -H "Authorization: Bearer $SLACK_TOKEN"
Expected:{ "ok": true, ... }. Ifok: falsewithinvalid_auth, the token is wrong or revoked. Risk: the token may appear in shell history; pass it through an environment variable and avoid logging the response. - Send a minimal plain-text message. Replace
$SLACK_BOT_TOKENand$CHANNEL_ID.curl -X POST https://slack.com/api/chat.postMessage \ -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"channel": "$CHANNEL_ID", "text": "diagnostic test"}'This requires thechat:writescope for the target channel (orchat:write.publicfor public channels when the app is not joined). Expected:ok: true. Common errors:not_in_channel,channel_not_found,ratelimited. - Inspect rate-limit headers. Use
curl -ior-D -to view headers. Look forX-Rate-Limit-RemainingandRetry-After. IfRetry-Afteris present, wait that many seconds before retrying. - Check channel status and membership. Call
conversations.infofor the channel. Confirmis_archivedis false and that the app or user is a member. - Validate message size and structure. Slack messages are limited to 4,000 characters. Block Kit payloads must pass Slack's validation; simplify the payload and retest if the error is
msg_too_longor invalid blocks.
Fixes Tied to Findings
not_in_channelorchannel_not_found: Invite the app to the channel (/invite @appname) or confirm the user is a member. Bots must be invited to private channels before posting.- Missing scopes: In the Slack app configuration under OAuth & Permissions, add
chat:writeand reinstall the app. Test scope changes in a development workspace first; incorrect scope modifications can break bot functionality. - Rate limited: Stop retrying until the
Retry-Afterinterval passes, then implement exponential backoff in your code. Immediate retries can extend the blockout. - Archived channel: Unarchive the channel or send to an active channel.
- Message too long: Split the message into multiple messages or shorten the text.
- Content filter or DLP block: Enterprise workspaces may block specific links or phrases. Rephrase the message and retest, or contact your workspace admin.
Changing OAuth scopes changes app state. If new scopes cause unexpected behavior, remove them from the app manifest and reinstall the previous configuration in the affected workspace.
Escalation Criteria
- The issue persists after 24 hours of applying the fixes above.
- Multiple users or channels are affected at once, which may indicate a Slack service incident or an org-wide policy.
- You are on Enterprise Grid and need Slack support or org-admin intervention.
- You cannot run
auth.testor read channel logs because you lack admin rights.
Limitations and Verification
This guide covers standard workspace messages and chat.postMessage bot calls. It does not cover Slack Connect external channels, Huddles, or Canvas publishing in detail. Slack-side delivery logs are not visible without workspace admin access.
Practical verification: send a plain-text test message to a private channel where you are an admin. Confirm the message appears and no error banner displays. For bots, confirm auth.test returns ok: true and chat.postMessage delivers to the target channel.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.