Slack API "rate_limited" HTTP 429 in CI
Slack throttles Web API methods per workspace and returns HTTP 429 with a Retry-After header and body {"ok":false,"error":"rate_limited"}. In CI this spikes when a matrix job posts a message per leg, or a retry loop hammers the same method.
What this error means
chat.postMessage returns HTTP 429 with a Retry-After seconds header. Some notifications post and others drop, usually correlated with large matrix fan-out.
< HTTP/2 429
< retry-after: 30
{"ok":false,"error":"rate_limited"}Common causes
Matrix fan-out posts one message per leg
A build matrix with many combinations each firing a notify step exceeds the per-method limit in a short window.
A retry loop ignores Retry-After
Retrying immediately after a 429 without waiting compounds the throttle instead of clearing it.
How to fix it
Respect the Retry-After header
- On a 429, read the
Retry-Aftervalue. - Sleep for that many seconds, then retry once.
- Do not retry in a tight loop.
resp=$(curl -s -D /tmp/h -o /tmp/b -w '%{http_code}' ... )
if [ "$resp" = "429" ]; then
wait=$(awk 'tolower($1)=="retry-after:"{print $2}' /tmp/h | tr -d '\r')
sleep "${wait:-30}"; # retry once
fiSend one summary message per workflow
Aggregate matrix results into a single notification in a final job rather than posting from each leg.
notify:
needs: [test]
if: always()
runs-on: ubuntu-latest
steps:
- run: ./scripts/notify-summary.shHow to prevent it
- Post a single aggregated status from a final job, not from each matrix leg.
- Always honor Retry-After before retrying a 429.
- Keep automated Slack traffic well under the per-method tier limits.