Slack Error Guide: 'too_many_attachments' — Fix Overloaded Messages
Fix the Slack too_many_attachments error: stay under the 100-attachment cap, move to Block Kit blocks, summarize large output, and thread details in chunks.
- #slack
- #api
- #troubleshooting
- #errors
Stuck on this Slack error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
The too_many_attachments error is returned by chat.postMessage (and chat.update) when a single message includes more than the maximum number of legacy attachments Slack allows — 100 per message. It is most common in DevOps tooling that maps each item in a list (failing tests, changed files, scan findings, hosts) to one attachment and posts them all in a single message. The fix is either to cap and paginate the items, or — better — to move off legacy attachments to Block Kit blocks, which are the modern, richer surface.
Slack returns HTTP 200 with ok:false:
{
"ok": false,
"error": "too_many_attachments"
}
It occurs whenever the attachments array exceeds 100 entries in one API call.
Symptoms
chat.postMessagefails only for large result sets (small ones succeed).- A report that “usually works” breaks after a big deploy or a noisy scan.
- One-attachment-per-item loops that grow unbounded with input size.
- The same code works until the underlying list crosses ~100 items.
Common Root Causes
1. One attachment per list item
Building attachments by appending an entry for every finding/test/host, with no cap, eventually exceeds 100.
2. Aggregating many sources into one message
Merging results from multiple jobs into a single message multiplies attachment count.
3. Legacy attachments instead of blocks
Sticking with the deprecated attachments field keeps you under its 100-item ceiling; blocks is the modern path with a higher, more flexible limit (up to 50 blocks per message, richer layout).
4. No pagination or truncation
Unbounded output with no “and N more…” summarization.
Diagnostic Workflow
Step 1: Reproduce with an oversized attachments array
# Build 101 trivial attachments and post them
ATT=$(python3 -c 'import json; print(json.dumps([{"text": f"item {i}"} for i in range(101)]))')
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d "{\"channel\":\"C0123456789\",\"attachments\":$ATT}" | jq .error
"too_many_attachments"
Step 2: Count attachments before sending
echo "$ATT" | jq 'length'
101
Any count over 100 will be rejected — validate this client-side before the call.
Step 3: Cap the list and add a summary
# Keep the first 95 and append a summary line for the rest
CAPPED=$(echo "$ATT" | jq '.[:95] + [{"text":"…and 6 more (truncated)"}]')
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d "{\"channel\":\"C0123456789\",\"attachments\":$CAPPED}" | jq '{ok}'
{
"ok": true
}
Step 4: Prefer Block Kit blocks
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d '{
"channel":"C0123456789",
"blocks":[
{"type":"header","text":{"type":"plain_text","text":"Scan results"}},
{"type":"section","text":{"type":"mrkdwn","text":"*12* findings — see thread for details"}}
]
}' | jq '{ok, ts}'
{
"ok": true,
"ts": "1720526400.001900"
}
Post the summary as blocks, then push details into the thread.
Example Root Cause Analysis
A CI bot posts one attachment per failing test. A large regression run produces 140 failures and the notification never appears:
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d "{\"channel\":\"C0123456789\",\"attachments\":$FAILING_TESTS}" | jq .error
"too_many_attachments"
The bot maps every failing test to an attachment with no ceiling, so 140 tests exceed the 100 cap. The fix is to post a summary block with the count, attach only the top offenders, and thread the full list in chunks:
# 1) Summary message
TS=$(curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d '{"channel":"C0123456789","text":":x: 140 tests failed — details in thread"}' | jq -r '.ts')
# 2) Threaded chunks of <=100
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d "{\"channel\":\"C0123456789\",\"thread_ts\":\"$TS\",\"attachments\":$FIRST_100}" | jq .ok
true
Summarizing in the root message and threading capped chunks keeps every call under the limit and the channel readable.
Prevention Best Practices
- Validate
attachments.length <= 100(andblocks.length <= 50) client-side before posting. - Migrate from legacy
attachmentsto Block Kitblocksfor richer, better-supported layouts. - Summarize large result sets (“N findings”) in the root message and thread the details in capped chunks.
- Truncate with an explicit “…and N more” and a link to the full report rather than dumping everything inline.
- Paginate long output across threaded replies instead of one giant message.
- For ad-hoc triage, the free incident assistant can help restructure an oversized report into a summary + thread. See more in Slack guides.
Quick Command Reference
# Count attachments before sending
echo "$ATT" | jq 'length'
# Cap to 95 + a truncation note
echo "$ATT" | jq '.[:95] + [{"text":"…and more (truncated)"}]'
# Post a Block Kit summary instead of many attachments
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" -H "Content-Type: application/json" \
-d '{"channel":"C0123456789","blocks":[{"type":"section","text":{"type":"mrkdwn","text":"*12* findings"}}]}' | jq .ok
Conclusion
too_many_attachments means a single message exceeded the 100 legacy-attachment cap. The usual root causes:
- One attachment per list item with no ceiling.
- Merging many sources into one message.
- Staying on legacy
attachmentsinstead ofblocks. - No pagination or truncation of large output.
Cap the array below 100, prefer Block Kit blocks, summarize the count in the root message, and thread the details in chunks.
Fixed it? Get 500 Slack & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.